一.继承的基本语法

#include<iostream>
using namespace std; //基类 Pelple
class People{
public:
void setname(char *name);
void setage(int age);
char *getname();
int getage();
private:
char *m_name;
int m_age;
};
void People::setname(char *name){ m_name = name; }
void People::setage(int age){ m_age = age; }
char* People::getname(){ return m_name; }
int People::getage(){ return m_age;} //派生类 Student
class Student: public People{
public:
void setscore(float score);
float getscore();
private:
float m_score;
};
void Student::setscore(float score){ m_score = score; }
float Student::getscore(){ return m_score; } int main(){
Student stu;
stu.setname("小明");
stu.setage();
stu.setscore(95.5f);
cout<<stu.getname()<<"的年龄是 "<<stu.getage()<<",成绩是 "<<stu.getscore()<<endl; return ;
}

继承的基本语法为:

class 派生类名:[继承方式] 基类名{
派生类新增加的成员
};

在本例中,class 后面的“Student”是新声明的子类,冒号后面的“People”是已经存在的基类。在“People”之前有一关键宇 public,用来表示是公有继承。继承方式包括 public(公有的)、private(私有的)和 protected(受保护的),此项是可选的,如果不写,那么默认为 private。

二.继承权限和继承方式

public、protected、private 指定继承方式

不同的继承方式会影响基类成员在派生类中的访问权限。

1) public继承方式

  • 基类中所有 public 成员在派生类中为 public 属性;
  • 基类中所有 protected 成员在派生类中为 protected 属性;
  • 基类中所有 private 成员在派生类中不能使用。

2) protected继承方式

  • 基类中的所有 public 成员在派生类中为 protected 属性;
  • 基类中的所有 protected 成员在派生类中为 protected 属性;
  • 基类中的所有 private 成员在派生类中不能使用。

3) private继承方式

    • 基类中的所有 public 成员在派生类中均为 private 属性;
    • 基类中的所有 protected 成员在派生类中均为 private 属性;
    • 基类中的所有 private 成员在派生类中不能使用。

例:

#include<iostream>
using namespace std; //基类People
class People{
public:
void setname(char *name);
void setage(int age);
void sethobby(char *hobby);
char *gethobby();
protected:
char *m_name;
int m_age;
private:
char *m_hobby;
};
void People::setname(char *name){ m_name = name; }
void People::setage(int age){ m_age = age; }
void People::sethobby(char *hobby){ m_hobby = hobby; }
char *People::gethobby(){ return m_hobby; } //派生类Student
class Student: public People{
public:
void setscore(float score);
protected:
float m_score;
};
void Student::setscore(float score){ m_score = score; } //派生类Pupil
class Pupil: public Student{
public:
void setranking(int ranking);
void display();
private:
int m_ranking;
};
void Pupil::setranking(int ranking){ m_ranking = ranking; }
void Pupil::display(){
cout<<m_name<<"的年龄是"<<m_age<<",考试成绩为"<<m_score<<"分,班级排名第"<<m_ranking<<",TA喜欢"<<gethobby()<<"。"<<endl;
} int main(){
Pupil pup;
pup.setname("小明");
pup.setage();
pup.setscore(92.5f);
pup.setranking();
pup.sethobby("乒乓球");
pup.display(); return ;
}

也可以使用using关键字来改变访问权限

#include<iostream>
using namespace std;
//基类People
class People{
public:
void show();
protected:
char *m_name;
int m_age;
};
void People::show(){
cout<<m_name<<"的年龄是"<<m_age<<endl;
}
//派生类Student
class Student: public People{
public:
void learning();
public:
using People::m_name; //将private改为public
using People::m_age; //将private改为public
float m_score;
private:
using People::show; //将public改为private
};
void Student::learning(){
cout<<"我是"<<m_name<<",今年"<<m_age<<"岁,这次考了"<<m_score<<"分!"<<endl;
}
int main(){
Student stu;
stu.m_name = "小明";
stu.m_age = ;
stu.m_score = 99.5f;
stu.show(); //compile error
stu.learning();
return ;
}

三.调用子类构造函数时必须先调用父类构造函数

和Java中子类的构造函数初始化相似,当需要对父类的私有成员变量进行初始化时,需要调用父类的构造函数。

例:

#include<iostream>
using namespace std;
//基类People
class People{
protected:
char *m_name;
int m_age;
public:
People(char*, int);
};
People::People(char *name, int age): m_name(name), m_age(age){}
//派生类Student
class Student: public People{
private:
float m_score;
public:
Student(char *name, int age, float score);
void display();
};
//People(name, age)就是调用基类的构造函数
Student::Student(char *name, int age, float score): People(name, age), m_score(score){ }
void Student::display(){
cout<<m_name<<"的年龄是"<<m_age<<",成绩是"<<m_score<<"。"<<endl;
}
int main(){
Student stu("小明", , 90.5);
stu.display();
return ;
}

运行结果:

小明的年龄是16,成绩是90.5。

若不显示指明父类的构造函数,则默认调用父类的无参构造函数,例:

#include <iostream>
using namespace std;
//基类People
class People{
public:
People(); //基类默认构造函数
People(char *name, int age);
protected:
char *m_name;
int m_age;
};
People::People(): m_name("xxx"), m_age(){ }
People::People(char *name, int age): m_name(name), m_age(age){}
//派生类Student
class Student: public People{
public:
Student();
Student(char*, int, float);
public:
void display();
private:
float m_score;
};
Student::Student(): m_score(0.0){ } //派生类默认构造函数
Student::Student(char *name, int age, float score): People(name, age), m_score(score){ }
void Student::display(){
cout<<m_name<<"的年龄是"<<m_age<<",成绩是"<<m_score<<"。"<<endl;
}
int main(){
Student stu1;
stu1.display();
Student stu2("小明", , 90.5);
stu2.display();
return ;
}

运行结果:

xxx的年龄是0,成绩是0。
小明的年龄是16,成绩是90.5。

注意:如果将People类中的无参构造函数删除,则会发生编译错误!因为Student类的第一个构造函数没有显示的声明父类的构造函数,因此编译器就会寻找父类的无参构造函数,若发现父类没有无参构造函数,则会出现错误!

四.子类的析构函数会优先于父类的析构函数被调用

#include <iostream>
using namespace std;
class A{
public:
A(){cout<<"A constructor"<<endl;}
~A(){cout<<"A destructor"<<endl;}
};
class B: public A{
public:
B(){cout<<"B constructor"<<endl;}
~B(){cout<<"B destructor"<<endl;}
};
class C: public B{
public:
C(){cout<<"C constructor"<<endl;}
~C(){cout<<"C destructor"<<endl;}
};
int main(){
C test;
return ;
}

运行结果:

多继承下的构造函数与析构函数

#include <iostream>
using namespace std; //基类
class BaseA{
public:
BaseA(int a, int b);
~BaseA();
protected:
int m_a;
int m_b;
};
BaseA::BaseA(int a, int b): m_a(a), m_b(b){
cout<<"BaseA constructor"<<endl;
}
BaseA::~BaseA(){
cout<<"BaseA destructor"<<endl;
} //基类
class BaseB{
public:
BaseB(int c, int d);
~BaseB();
protected:
int m_c;
int m_d;
};
BaseB::BaseB(int c, int d): m_c(c), m_d(d){
cout<<"BaseB constructor"<<endl;
}
BaseB::~BaseB(){
cout<<"BaseB destructor"<<endl;
} //派生类
class Derived: public BaseA, public BaseB{
public:
Derived(int a, int b, int c, int d, int e);
~Derived();
public:
void show();
private:
int m_e;
};
Derived::Derived(int a, int b, int c, int d, int e): BaseA(a, b), BaseB(c, d), m_e(e){
cout<<"Derived constructor"<<endl;
}
Derived::~Derived(){
cout<<"Derived destructor"<<endl;
}
void Derived::show(){
cout<<m_a<<", "<<m_b<<", "<<m_c<<", "<<m_d<<", "<<m_e<<endl;
} int main(){
Derived obj(, , , , );
obj.show();
return ;
}

运行结果:

BaseA constructor
BaseB constructor
Derived constructor
1, 2, 3, 4, 5
Derived destructor
BaseB destructor
BaseA destructor

五.当多个父类中有同名的成员时,子类在调用时,需要在成员名字前加::

当两个或多个基类中有同名的成员时,如果直接访问该成员,就会产生命名冲突,编译器不知道使用哪个基类的成员。这个时候需要在成员名字前面加上类名和域解析符::,以显式地指明到底使用哪个类的成员,消除二义性。

例:

#include <iostream>
using namespace std; //基类
class BaseA{
public:
BaseA(int a, int b);
~BaseA();
public:
void show();
protected:
int m_a;
int m_b;
};
BaseA::BaseA(int a, int b): m_a(a), m_b(b){
cout<<"BaseA constructor"<<endl;
}
BaseA::~BaseA(){
cout<<"BaseA destructor"<<endl;
}
void BaseA::show(){
cout<<"m_a = "<<m_a<<endl;
cout<<"m_b = "<<m_b<<endl;
} //基类
class BaseB{
public:
BaseB(int c, int d);
~BaseB();
void show();
protected:
int m_c;
int m_d;
};
BaseB::BaseB(int c, int d): m_c(c), m_d(d){
cout<<"BaseB constructor"<<endl;
}
BaseB::~BaseB(){
cout<<"BaseB destructor"<<endl;
}
void BaseB::show(){
cout<<"m_c = "<<m_c<<endl;
cout<<"m_d = "<<m_d<<endl;
} //派生类
class Derived: public BaseA, public BaseB{
public:
Derived(int a, int b, int c, int d, int e);
~Derived();
public:
void display();
private:
int m_e;
};
Derived::Derived(int a, int b, int c, int d, int e): BaseA(a, b), BaseB(c, d), m_e(e){
cout<<"Derived constructor"<<endl;
}
Derived::~Derived(){
cout<<"Derived destructor"<<endl;
}
void Derived::display(){
BaseA::show(); //调用BaseA类的show()函数
BaseB::show(); //调用BaseB类的show()函数
cout<<"m_e = "<<m_e<<endl;
} int main(){
Derived obj(, , , , );
obj.display();
return ;
}

运行结果:

C++语言基础(9)-继承的更多相关文章

  1. Object Pascal 语言基础

    Delphi 是以Object Pascal 语言为基础的可视化开发工具,所以要学好Delphi,首先要掌握的就是Object Pascal 语言.Object Pascal语言是Pascal之父在1 ...

  2. Java学习笔记:语言基础

    Java学习笔记:语言基础 2014-1-31   最近开始学习Java,目的倒不在于想深入的掌握Java开发,而是想了解Java的基本语法,可以阅读Java源代码,从而拓展一些知识面.同时为学习An ...

  3. JavaScript 语言基础

    js语言基础 一 基本知识 UniCode编码 区分大小写(HTML不区分/XHTML区分) Unicode转义序列 \uxxxx (\u加4位16进制表示) 注释 单行注释:// 多行注释:/* * ...

  4. 20165318 预备作业二 学习基础和C语言基础调查

    20165318 学习基础和C语言基础调查 技能学习经验 我们这一代人,或多或少的都上过各种兴趣班,舞蹈钢琴画画书法,我也是如此.可这些技能中,唯一能拿的出手的就是舞蹈了.按照<优秀的教学方法- ...

  5. Go语言基础之结构体

    Go语言基础之结构体 Go语言中没有“类”的概念,也不支持“类”的继承等面向对象的概念.Go语言中通过结构体的内嵌再配合接口比面向对象具有更高的扩展性和灵活性. 类型别名和自定义类型 自定义类型 在G ...

  6. 我的学习目标(目前已初步学习完Java语言基础)

    操作系统.尤其是内存/线程/进程方面 计算机网络协议,重点关注 TCP/UDP/HTTP. 数据结构与算法. 数据库 设计模式,熟练掌握常用的几种设计模式. Java语言基础.熟悉java语言基础,了 ...

  7. 20165223 学习基础和C语言基础调查

    一.学习基础 1. 我所擅长的技能 从小我就对新鲜事物抱有浓厚的兴趣,因此多年来培养了许多爱好,对感兴趣的诸如绘画方面的国画.油画.素描.漫画等:音乐方面的钢琴.吉他.架子鼓等:运动方面的滑板.溜冰. ...

  8. 20165232 学习基础和c语言基础调查

    做中学读后感 学习是要思考的,仅仅实践是不够的: 不光会动手,还要理解背后的原理 不光会用工具,还要理解支撑的理论 技能是分层次的: 一项技能的掌握程度分为:新手/高级初学者/合格者/精通/专家 对技 ...

  9. 20165237 学习基础和C语言基础调查

    学习基础和C语言基础调查 一.技能学习与特长 你有什么技能比大多人(超过90%以上)更好? 我的爱好和技能说实话挺广泛的.如果要挑出来一个很擅长的话,我觉得应该是钢琴. 针对这个技能的获取你有什么成功 ...

随机推荐

  1. Mysql数据库的安装及配置

    本文转载自http://www.cnblogs.com/xiaoluo501395377/archive/2013/04/07/3003278.html 如果要在Linux上做j2ee开发,首先得搭建 ...

  2. python3-关于GitHub的最基本操作

    阅读目录 介绍 什么是GitHub? 创建存储库 创建一个分支 做一个提交 打开拉取请求 合并拉取请求 一.介绍 Hello World项目是计算机编程历史悠久的传统.这是一个简单的练习,可以让你在学 ...

  3. python3开发进阶-Django框架的详解

    一.MVC框架和MTV框架 MVC,全名是Model View Controller,是软件工程中的一种软件架构模式,把软件系统分为三个基本部分: 模型(Model).视图(View)和控制器(Con ...

  4. 【OpenJudge8464】【序列DP】股票买卖

    股票买卖 总时间限制: 1000ms 内存限制: 65536kB [描述] 最近越来越多的人都投身股市,阿福也有点心动了.谨记着“股市有风险,入市需谨慎”,阿福决定先来研究一下简化版的股票买卖问题. ...

  5. IOS,苹果内购和添加广告

    内购——应用内购买 通过苹果应用程序商店有三种主要赚钱的方式: 直接收费(与国内大部分用户的消费习惯相悖) 广告(降低用户体验 应用程序名称带Lite可以添加广告) O2O -> Online推 ...

  6. linux-改变文件属主权限-chown

    http://www.cnblogs.com/peida/archive/2012/12/04/2800684.html chown将指定文件的拥有者改为指定的用户或组,用户可以是用户名或者用户ID: ...

  7. Java杂谈2——引用与跟搜索算法

    Java中的引用 Java“引用”的概念源于C++,原本的定义相当有限:一个引用(Reference)代表的内存通常用于指向另一块内存区域的起始地址.通过引用类型保存的起始地址,可以找到这个引用所指向 ...

  8. Linux下#!/usr/bin/env bash和#!/usr/bin/bash、#!/bin/bash的比较

    #!/usr/bin/env bash #在不同的系统上提供了一些灵活性. #!/usr/bin/bash #将对给定的可执行文件系统进行显式控制. 通过/usr/bin/env运行程序,用户不需要去 ...

  9. 分析器错误 未能加载类型“XX.WebApiApplication”

    解决方案,删除bin目录下内容(有单独使用dll的删除前请先备份) 清理解决方案并重新生成

  10. faststone 注册码

    用户名:c1ikm密码:AXMQX-RMMMJ-DBHHF-WIHTV 或 AXOQS-RRMGS-ODAQO-APHUU