如何上传网站到空间,大学生做网站怎么赚钱,广州网站排名推广公司,建设领域工人管理网站继承
一个类#xff0c;继承另一个已有的类。#xff08;在一个已存在的类的基础上建立一个新的类#xff0c;并拥有其特性#xff09; 是一个父类#xff08;基类#xff09;派生出子类#xff08;派生类#xff09;的过程。 派生类往往是基类的具象化#xff0c;基…继承
一个类继承另一个已有的类。在一个已存在的类的基础上建立一个新的类并拥有其特性 是一个父类基类派生出子类派生类的过程。 派生类往往是基类的具象化基类则是派生类的抽象。 基类与派生类是相对的一个类可能存在又是基类又是派生类的情况。 继承提高了代码的复用性。 在实际的使用中派生类会做出一些与基类的差异化 ● 修改继承来自的基类内容 属性公有属性直接修改私有属性通过接口修改 函数函数隐藏通过派生类实现一个同名同参数的函数来隐藏基类的函数。 ● 新增派生类的内容 #include iostream
using namespace std;// 基类
class Father
{
private:string name 张;public:void set_name(const string name){this-name name;}string get_name(){return name;}void work(){cout 我的工作是厨师我负责炒菜。 endl;}
};// 派生类继承基类
class Son:public Father
{
public:void init(){set_name(王); // 私有属性通过接口修改}void work(){cout 我是飞行员我要上天。 endl;}void game(){cout 三硝基甲苯。 endl;}
};int main()
{Son s;cout s.get_name() endl; // 张s.init();cout s.get_name() endl; // 王s.work(); // s.game();// 调用基类被隐藏的成员函数s.Father::work();return 0;
}继承的格式、权限
class 类名:父类名 {}; // 默认权限是 privateclass 类名:继承的权限 父类名 {};继承时类中的特殊成员函数不会被继承
构造函数
派生类中的任意一个构造函数都必须直接或者间接调用基类的一个构造函数。
problem
#include iostream
using namespace std;class Father
{string secret;
public:string firstname;float asset;Father(string secret, string fname, float asset):secret(secret), firstname(fname), asset(asset){cout A constructor of father class with parameters. endl;}
};class Son:public Father
{string secret;
public:void show(){cout First name: firstname endl;}};int main()
{// Son s1; // 找不到基类的无参构造函数 // error因为父类只有有参构造而子类中没有提供 能够调用父类有参构造的构造函数不能成功创建父类的空间// Son s2(~, 0, 1); // 找不到匹配的构造函数cout Size of father: sizeof(Father) endl;cout Size of son: sizeof(Son) endl;return 0;
}solution1补充基类的无参构造函数
#include iostream
using namespace std;class Father
{string secret;
public:string firstname;float asset;Father():secret(~), firstname(w), asset(1000000) { }Father(string secret, string fname, float asset):secret(secret), firstname(fname), asset(asset){cout A constructor of father class with parameters. endl;}
};class Son:public Father
{string secret;
public:void show(){cout First name: firstname endl;}};int main()
{Son s1;s1.show();// Son s2(~, 0, 1); // 找不到匹配的构造函数cout Size of father: sizeof(Father) endl;cout Size of son: sizeof(Son) endl;return 0;
}solution2透传构造
需要 在子类构造函数的初始化列表中 显性调用父类的构造函数 当父类中只有有参构造子类在创建类对象时必须手动调用父类的构造函数。
#include iostream
using namespace std;class Father
{string secret;
public:string firstname;float asset;Father(string fname, float asset):firstname(fname), asset(asset){cout A constructor of father class with parameters. endl;}
};class Son:public Father
{string secret;
public: Son():Father(default string, 120000)//, secret(0) // 这里使用具体的值{ }// Father(fname, asset) 和 secret(secret) 可以交换但有警告Son(string fname, float asset, string secret):Father(fname, asset), secret(secret){}void show(){cout First name: firstname endl;cout Asset: asset endl;cout Secret of the son: secret endl;}
};int main()
{Son s1(Xing, 120000, secret1);s1.show();Son s2;s2.show();return 0;
}solution3继承构造C 11 支持
C支持 不用在子类中再写一遍父类的构造函数 ——
using Father::Father; // 在子类中使用父类的构造函数直接使用继承构造的方式不能对子类成员初始化。 继承构造本质上并不是把父类中的构造函数继承给子类编译器自动根据父类中构造函数的格式提供出派生的构造函数个数、参数都和父类中的构造函数一致主要还是通过透传构造创建父类的空间。
#include iostream
using namespace std;class Father
{string secret;
public:string firstname;float asset;Father():secret(~), firstname(w), asset(1000000){cout A constructor of father class with no parameters. endl;}Father(float asset):asset(asset){cout A constructor of father class with only one parameter. endl;}Father(string fname, float asset):firstname(fname), asset(asset){cout A constructor of father class with two parameters. endl;}Father(Father other):firstname(other.firstname), asset(other.asset) // 拷贝构造{cout Duplicator_constructor of father class. endl;}
};class Son:public Father
{string secret;using Father::asset; // 把父类中公有继承下来的 asset 成员在子类中改成私有权限using Father::Father;public:void show(){cout First name: firstname endl;cout Asset: asset endl;cout Secret of the son: secret endl;}
};int main()
{Son s0;s0.show();Son s1(120000);s1.show();Son s2(Xing, 120000);s2.show();Son s3 s2;s3.show();return 0;
}solution4委托构造
一个类的构造函数可以调用这个类中的另一个构造函数但是要避免循环委托。 委托构造的性能低于透传构造但是代码维护性更好因为通常一个类中构造函数都会委托给能力最强参数最多的构造函数代码重构时只需要更改这个参数最多的构造函数即可。
只有一个类
并不直接通过无参构造实例化对象而是无参构造委托有参构造从而实例化对象。
#include iostream
using namespace std;class Son
{string secret;
public:Son():Son(secret0){cout A constructor of child class without parameters. endl;}Son(string secret):secret(secret){cout A constructor of child class with parameter(s). endl;}void show(){cout Secret of the son: secret endl;}
};int main()
{Son s0;s0.show();Son s1(secret1);s1.show();return 0;
}父子类的继承 #include iostream
using namespace std;class Father
{string secret;
public:string firstname;float asset;Father(string fname, float asset):firstname(fname), asset(asset){cout A constructor of father class with two parameters. endl;}Father(float asset):asset(asset){cout A constructor of father class with only one parameter. endl;}
};class Son:public Father
{string secret;public:Son():Son(secret0){cout A constructor of child class without parameters. endl;}Son(string secret):Father(Xing, 120000), secret(secret){cout A constructor of child class with parameter(s). endl;}void show(){cout First name: firstname endl;cout Asset: asset endl;cout Secret of the son: secret endl;}
};int main()
{Son s0;s0.show();return 0;
}拷贝构造函数
需要在初始化列表中显性调用父类的拷贝构造传 other 对象到父类的拷贝构造中。
#include iostream
using namespace std;class Father
{string secret;
public:string firstname;float asset;Father(string fname, float asset):firstname(fname), asset(asset){cout A constructor of father class with two parameters. endl;}Father(float asset):asset(asset){cout A constructor of father class with only one parameter. endl;}Father(Father other):firstname(other.firstname), asset(other.asset){cout Duplicator_constructor of father class. endl;}
};class Son:public Father
{string secret;public:Son(string fname, float asset, string secret):Father(fname, asset), secret(secret){}Son(Son other):Father(other), secret(other.secret){cout Duplicator_constructor of child class. endl;}void show(){cout First name: firstname endl;cout Asset: asset endl;cout Secret of the son: secret endl;}
};int main()
{Son s1(Xing, 120000, secret1);s1.show();Son s2 s1;s2.show();return 0;
}继承时构造和析构的时机
子类在继承父类时会先把父类中的成员保留一份再来创建子类自己的成员。 父类先构造子类后构造。子类先析构父类后析构。
#include iostream
using namespace std;class Father
{string secret;
public:string firstname;float asset;Father(string fname, float asset):firstname(fname), asset(asset){cout A constructor of father class with two parameters. endl;}Father(float asset):asset(asset){cout A constructor of father class with only one parameter. endl;}~Father() // 注意这里没有用虚析构函数{cout Destructor of father class. endl;}
};class Son:public Father
{string secret;
public:Son():Father(default string, 120000) // 这里使用具体的值{cout A constructor of child class with no parameters. endl;}Son(string fname, float asset, string secret):Father(fname, asset), secret(secret){cout A constructor of child class with parameters. endl;}~Son(){cout Destructor of child class. endl;}
};int main()
{Son *s new Son;delete s;s nullptr;cout endl;Son *ss new Son(z, 1200000, 0);delete ss;ss nullptr;cout endl;Father *sss new Son();delete sss;sss nullptr;cout endl;Father *ssss new Son(z, 1200000, 0);delete ssss;ssss nullptr;cout endl;return 0;
}当父子类中存在同名成员
访问时不会发生冲突默认访问子类的成员变量。
#include iostream
using namespace std;class Father
{string secret;
public:string firstname;float *asset;Father():asset(new float){cout A constructor of father class without parameters. endl;}~Father(){delete asset;cout Destructor of father class. endl;}
};class Son:public Father
{string secret;public:float *asset;Son():asset(new float){cout A constructor of child class without parameters. endl;}~Son(){delete asset;cout Destructor of child class. endl;}};int main()
{Son *m new Son;*(m-asset) 140000;cout *(m-asset): *(m-asset) endl;cout *(m-Father::asset): *(m-Father::asset) endl;delete m;m nullptr;return 0;
}多重继承
一个子类继承自多个基类。
格式 class 类名:继承权限 父类名, 继承权限 父类名, … { }; 1、当多个父类中包含同名成员
多个父类中包含同名成员通过 域限定符 访问指定的父类中成员。
#include iostream
using namespace std;class Father
{string secret;
public:void act_1(){cout Earn money. endl;}
};class Son:public Father
{string secret;public:void act_1(){cout Save money. endl;}void act_2(){cout Inherit money. endl;}
};class Grandchild:public Father, public Son
{
};int main()
{Son s;s.act_1();s.Father::act_1();Grandchild g;g.act_2();g.Son::act_2();return 0;
}2、菱形继承钻石继承 A ------ 公共基类/ \B C ------ 中间子类\ /D ------ 汇集子类汇集子类中会包含多份公共基类中的内容。 Problems ——
1、会发生二义性的问题同一个变量或者函数可以通过两种方法访问 2、如果公共基类过大会造成汇集子类中的代码 膨胀 / 冗余。
#include iostream
using namespace std;class A
{
public:int a;
};class B:public A
{
};class C:public A
{
};class D:public C, public B
{
};int main()
{D d0;d0.C::a 100;cout In C: d0.C::a endl; // 100d0.B::a 90; // 可以直接通过中间子类访问直接访问 B 中的 a成员cout In B: d0.B::a endl; // 90// d0.B::A::a 80; // 以下四行报错// cout d0.B::A::a endl; // d0.C::A::a 70;// cout d0.C::A::a endl; // 会发生二义性因为有两条路径都可以访问到 Areturn 0;
}虚继承virtual
虚继承指对公共基类的虚继承。 主要用于解决菱形继承问题采用虚继承后公共基类中的内容只会在汇集子类中存在一份在汇集子类中可以通过任意一条路径访问到公共基类中的成员。在中间子类继承时加 virtual。 虚继承解决二义性主要通过虚基类指针和虚基类表实现下例中的 类B、类C 会分别创建一个虚基类指针和虚基类表。所有同类型对象共用一张虚基类表每个对象内部增加一个隐藏的虚基类指针成员变量这个虚基类指针指向虚基类表。派生类D 中也有隐藏的虚基类指针但是没有自己虚基类表。在调用 A的成员时 D对象 会通过虚基类指针找到对应的虚基类表通过查表避免二义性。
—— Solution
#include iostream
using namespace std;class A
{
public:int a;
};class B:virtual public A
{
};class C:virtual public A
{
};class D:public B, public C
{
};int main()
{D d0;d0.B::A::a 90;cout d0.C::A::a endl; // 成功打印 90上一个问题得以解决return 0;
}为每一个类添加构造函数
#include iostream
using namespace std;class A
{
public:int a;A(int a):a(a) {cout A endl; }
};class B:virtual public A
{
public:int b;B(int a, int b):A(a), b(b) {cout B endl; }
};class C:virtual public A
{
public:C(int a):A(a) {cout C endl; } // B 和 C 哪一个先构造取决于 D 在继承时的顺序
};class D:public C, public B // 决定结果的顺序 为 C、B
{
public:D(int a, int b):B(a, b), C(a), A(a) {cout D endl; } // B、C 可交换顺序结果不变
};int main()
{D d0(12, 5);cout d0.a \t d0.b endl;d0.B::A::a 90;cout d0.C::A::a endl;return 0;
}#include iostream
using namespace std;class A
{
public:int a;A(int a):a(a) {cout A endl; }
};class B:virtual public A
{
public:int b;B(int a, int b):A(a), b(b) {cout B endl; }
};class C:virtual public A
{
public:C(int a):A(a) {cout C endl; } // B 和 C 哪一个先构造取决于 D 在继承时的顺序
};class D:public B, public C
{
public:D(int a, int b):C(a), B(a, b), A(a) {cout D endl; } // B、C 可交换顺序
};int main()
{D d0(12, 5);cout d0.a \t d0.b endl;d0.B::A::a 90;cout d0.C::A::a endl;return 0;
}B 和 C 哪一个先构造取决于 D 在继承时的顺序。