|
|
强悍的水煮肉 · C++类的继承_c++ ...· 2 月前 · |
|
|
强悍的水煮肉 · 面向对象特征二:继承(Inheritance ...· 2 月前 · |
|
|
强悍的水煮肉 · Objective-C类的继承_object ...· 2 月前 · |
|
|
强悍的水煮肉 · C++ 继承| 菜鸟教程· 2 月前 · |
|
|
强悍的水煮肉 · Msvm_VirtualHardDiskSe ...· 2 月前 · |
面向对象程序设计中最重要的一个概念是继承。继承允许我们依据另一个类来定义一个类,这使得创建和维护一个应用程序变得更容易。这样做,也达到了重用代码功能和提高执行效率的效果。
当创建一个类时,您不需要重新编写新的数据成员和成员函数,只需指定新建的类继承了一个已有的类的成员即可。这个已有的类称为 基类 ,新建的类称为 派生类 。
继承代表了 is a 关系。例如,哺乳动物是动物,狗是哺乳动物,因此,狗是动物,等等。
代码如下:
// 基类一个类可以派生自多个类,这意味着,它可以从多个基类继承数据和函数。定义一个派生类,我们使用一个类派生列表来指定基类。类派生列表以一个或多个基类命名,形式如下:
class derived-class: access-specifier base-class其中,访问修饰符 access-specifier 是 public、protected 或 private 其中的一个,base-class 是之前定义过的某个类的名称。如果未使用访问修饰符 access-specifier,则默认为 private。
假设有一个基类 Shape , Rectangle 是它的派生类,如下所示:
当上面的代码被编译和执行时,它会产生下列结果:
Total area: 35派生类可以访问基类中所有的非私有成员。因此基类成员如果不想被派生类的成员函数访问,则应在基类中声明为 private。
我们可以根据访问权限总结出不同的访问类型,如下所示:
访问publicprotectedprivate 同一个类yesyesyes 派生类yesyesno 外部的类yesnono一个派生类继承了所有的基类方法,但下列情况除外:
当一个类派生自基类,该基类可以被继承为 public、protected 或 private 几种类型。继承类型是通过上面讲解的访问修饰符 access-specifier 来指定的。
我们几乎不使用 protected 或 private 继承,通常使用 public 继承。当使用不同类型的继承时,遵循以下几个规则:
多继承即一个子类可以有多个父类,它继承了多个父类的特性。
C++ 类可以从多个类继承成员,语法如下:
class <派生类名>:<继承方式1><基类名1>,<继承方式2><基类名2>,… <派生类类体>其中,访问修饰符继承方式是 public、protected 或 private 其中的一个,用来修饰每个基类,各个基类之间用逗号分隔,如上所示。现在让我们一起看看下面的实例:
当上面的代码被编译和执行时,它会产生下列结果:
Total area: 35 Total paint cost: $2450 class B: virtual public D{......}; class A: virtual public D{......}; class C: public B, public A{.....};虚继承--(在创建对象的时候会创建一个虚表)在创建父类对象的时候
A:virtual public D B:virtual public D
#include <iostream>
using namespace std;
class D
public:
D(){cout<<"D()"<<endl;}
~D(){cout<<"~D()"<<endl;}
protected:
int d;
class B:virtual public D
public:
B(){cout<<"B()"<<endl;}
~B(){cout<<"~B()"<<endl;}
protected:
int b;
class A:virtual public D
public:
A(){cout<<"A()"<<endl;}
~A(){cout<<"~A()"<<endl;}
protected:
int a;
class C:public B, public A
public:
C(){cout<<"C()"<<endl;}
~C(){cout<<"~C()"<<endl;}
protected:
int c;
int main()
cout << "Hello World!" << endl;
C c; //D, B, A ,C
cout<<sizeof(c)<<endl;
return 0;
1、与类同名的函数是构造函数。
2、~ 类名的是类的析构函数。
孙程耿 孙程耿
951***452@qq.com
8年前 (2017-08-15)
为什么子类的构造函数中会出现在初始化列表中呢?原因在于子类能够从基类继承的内容限制上。
因此,我们不能够在子类的成员函数体中调用基类的构造函数来为成员变量进行初始化。例如这样子是不可以的
#include <iostream> using namespace std; // 基类 class Shape public: Shape(int w,int h) width=w; height=h; protected: int width; int height; // 派生类 class Rectangle: public Shape public: Rectangle(int a,int b) Shape(a,b);但我们可以把基类的构造函数放在子类构造函数的初始化列表上,以此实现调用基类的构造函数来为子类从基类继承的成员变量初始化。
#include <iostream> using namespace std; // 基类 class Shape public: Shape(int w,int h) width=w; height=h; protected: int width; int height; // 派生类 class Rectangle: public Shape public: Rectangle(int a,int b):Shape(a,b) };
SunnyClear
238***9834@qq.com
小鹤
799***970@qq.com
派生类在继承基类的成员变量时,会单独开辟一块内存保存基类的成员变量,因此派生类自己的成员变量即使和基类的成员变量重名,但是也不会引起冲突。如下代码:
#include <iostream> using namespace std; class A public: A(){n = 0;}; ~A(){}; int getA(){ return n;}; void setA(int t){ n = t;}; private: int n; //派生类 class B :public A public: B(){ n = 0;}; ~B(){}; int getB(){ return n;}; void setB(int t){ n = t;}; private: int n; int main(int argc, char * argv[]) b.setA(10); //设置基类的成员变量n cout<<"A::n "<<b.getA()<<endl; cout<<"B::n "<<b.getB()<<endl; b.setB(9); //设置派生类的成员变量n cout<<"A::n "<<b.getA()<<endl; cout<<"B::n "<<b.getB()<<endl; return 0;结果如下:
A::n 10 B::n 0 A::n 10 B::n 9
LiuJW0
308***9974@qq.com
ShenyanWu
208***1347@qq.com
补充二楼说法,派生类是会继承父类的构造方法的,但在继承构造方法时有一些注意事项,这在 C++11 以及之后的标准中得到了支持。具体情况取决于派生类是否定义了自己的构造方法以及父类构造方法的可访问性。
#define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std; class Base { public: Base() { num = 5; cout << "BaseConstructorCall:" << protectedMember << endl; Base(int n) { num = n; cout << "BaseConstructorCallnum:" << protectedMember << endl; ~Base() { cout << "BaseDestructorCall:" << protectedMember << endl; protected: int protectedMember = 0; int num; class Derived1 : public Base { public: using Base::Base; // 这行声明继承父类的构造方法 void modifyMember(int newValue) { protectedMember = newValue; // 修改父类的成员 cout << "Derived1:" << num << endl; class Derived2 : public Base { public: void modifyMember(int newValue) { protectedMember = newValue; // 修改同一个父类的成员 cout << "Derived2:" << num << endl; int main() { Derived1 d1(88); Derived2 d2; d1.modifyMember(10); d2.modifyMember(20); return 0; 可以在输出中看到Derived:88主要是需要使用基类构造定义:
using Base::Base; // 这行声明继承父类的构造方法
小凡
392***216@qq.com
#include <iostream> using namespace std; class Value{ public: Value(int x){ cout << "开始构造Value" << endl; value = x; int getValue() return value; ~Value() cout << "开始析构Value" << endl; private: int value; class Num{ public: Num(int y) cout << "开始构造Num" << endl; num = y; int getNum() return num; ~Num() cout << "开始析构Num" << endl; private: int num; class Test : public Value,public Num{ public: Test(int x,int y):Value(x),Num(y) cout << "开始构造Test" << endl; getAllInfo() cout << "value:" << getValue() << endl; cout << "num:" << getNum() << endl; ~Test() cout << "开始析构Test" << endl; int main(){ Test t(10,20); t.getAllInfo(); return 0;开始构造Value 开始构造Num 开始构造Test value:10 num:20 开始析构Test 开始析构Num 开始析构Value
不甘心
102***0588@qq.com
kebing
222***5090@qq.com
using Base::Base; // 这行声明继承父类的构造方法
void modifyMember(int newValue) {
protectedMember = newValue; // 修改父类的成员
cout << "Derived1:" << num << endl;
还可以直接使用列表调用基类的构造函数,即改为:
class Derived1 : public Base {
public:
Derived1(int n):Base(n) {//通过列表调用父类的构造函数
void modifyMember(int newValue) {
protectedMember = newValue; // 修改父类的成员
cout << "Derived1:" << num << endl;
};
|
|
强悍的水煮肉 · C++ 继承| 菜鸟教程 2 月前 |