目录
一、继承方式与权限问题
1.继承的写法
//父类 基类
class parent
{
};
//子类 派生类
//公有继承
class son1:public parent
{
public:
protected:
};
//保护继承
class son2:protected parent
{
public:
protected:
};
//私有继承
class son3:private parent
{
public:
protected:
};
//继承和派生
//继承: 子类中没有产生新的属性或者行为
//派生: 派生类中有新的属性和行为产生
class 子类名:继承方式 父类名
{
};
//继承方式 就是权限限定词
2.继承的实质与权限问题
● 继承的实质:父类的数据和成员子类中也有一份
#include<iostream>
#include<string>
using namespace std;
class Parent
{
public:
void print()
{
cout << name << "\t" << money << endl;
}
string& getWife()
{
return wife;
}
protected:
int money;
string name;
private:
string wife;
};
class son :public Parent
{
public:
void printSon()
{
print();
cout << name <<"\t" << money << endl;
//cout << wife << endl; -----父类中私有属性不能直接访问
cout << getWife() << endl; //间接通过父类的函数访问
}
protected:
};
int main()
{
son son1;
son1.printSon();
son1.print();
while (1);
return 0;
}
● 权限问题:继承方式只会增强父类属性在子类中的权限显示
public | protected | private | |
protected继承 | protected | protected | 不可直接访问 |
public继承 | public | protected | 不可直接访问 |
private继承 | private | private | 不可直接访问 |
//父类
class A
{
public:
int a1;
protected:
int a2;
private:
int a3;
};
//public继承
class B :public A
{
public:
//int a1;
protected:
//int a2;
private:
//int a3; 不能直接访问
};
//protected继承
class C :protected A
{
public:
protected:
//int a1; //public 显示protected
//int a2;
private:
//int a3; 不能直接访问
};
//private继承
class D :private A
{
public:
void print()
{
cout << a1 << endl;
cout << a2 << endl;
//cout << a3 << endl; //父类的私有属性不能直接访问
}
protected:
private:
//int a1;
//int a2;
//int a3; //父类的私有属性不能直接访问
};
//私有继承会导致当前父类 无法在孙子类有任何作用
class F :public D
{
public:
};
int main()
{
B b;
b.a1 = 123;
C c;
//c.a1 = 12; -----在子类中变为protected无法类外访问
while (1);
return 0;
}
二、继承中的构造函数
1.父类的属性通过父类的构造函数初始化
2.子类中的构造函数,必须要调用父类构造函数,必须采用初始化参数列表的方式
3.单继承和多继承的区别
● 单继承:只有一个父类
● 多继承:两个或两个以上的父类
4.继承的属性,无论被继承多少次,所以类一般不会被继承很多层,会导致类的臃肿。
#include <iostream>
#include <string>
using namespace std;
class Parent
{
public:
Parent() { cout << "父类无参构造函数" << endl; }
Parent(string FName, string SName):FName(FName), SName(SName){}
protected:
string FName;
string SName;
};
//单继承
class Son :public Parent
{
public:
//这种写法,父类必须存在无参的构造函数,当然缺省也可以
Son() { cout << "子类无参构造函数" << endl; }
Son(string FName, string SName, string sonSName) :Parent(FName,SName)
{
//自己的属性用什么办法初始化都行
this->sonFName = FName;
this->sonSName = sonSName;
}
void print()
{
cout << "父:" << FName + SName << endl;
cout << "子:" << sonFName + sonSName << endl;
}
protected:
string sonFName;
string sonSName;
//string FName;
//string SName;
};
//多继承
//欧田
//阳子
//欧阳 田子
class MM
{
public:
//MM() = default;
MM(string mmFName, string mmSName)
{
this->mmFName = mmFName;
this->mmSName = mmSName;
}
protected:
string mmFName;
string mmSName;
};
class GG
{
public:
//GG() = default;
GG(string ggFName, string ggSName)
{
this->ggFName = ggFName;
this->ggSName = ggSName;
}
protected:
string ggFName;
string ggSName;
};
class Girl :public GG,public MM
{
public:
//子类想要这种构造函数,每个父类都要有一个无参的构造函数
//Girl() {}
Girl(string mmFName, string mmSName, string ggFName, string ggSName)
:MM(mmFName,mmSName),GG(ggFName,ggSName)
{
girlFName = ggFName + mmFName;
girlSName = ggSName + mmSName;
}
void print()
{
cout << "父:" << ggFName + ggSName << endl;
cout << "母:" << mmFName + mmSName << endl;
cout << "女:" << girlFName + girlSName << endl;
}
protected:
string girlFName;
string girlSName;
};
//继承的属性一致都存在
class A
{
public:
A(int a) :a(a) {}
int a;
};
class B:public A
{
public:
B(int a,int b) :A(a),b(b) {}
int b;
};
class C :public B
{
public:
C(int a, int b,int c) :B(a,b),c(c) {}
int c;
};
class D :public C
{
public:
D(int a, int b, int c,int d) :C(a,b,c), d(d) {}
int d;
};
int main()
{
Son son; //子类构造对象,优先调用父类构造函数
Son son1("白", "老鬼", "日天");
son1.print();
Girl girl("阳", "子", "欧", "田");
girl.print();
return 0;
}
三、继承中的同名问题
1.数据成员同名
2.成员函数名同名
3.正常赋值调用
4.非正常赋值调用
#include <iostream>
using namespace std;
class MM
{
public:
MM(string name, int age) :name(name), age(age) {}
void print()
{
cout << "MM:";
cout << name << "\t" << age << endl;
}
protected:
string name;
int age;
};
class Girl :public MM
{
public:
Girl(string name, int age) :MM("父类", 28), name(name), age(age) {}
void print()
{
//不做特别处理,就近原则
cout << name<<"\t" << age << endl;
//类名限定
cout << MM::name << "\t" << MM::age << endl;
//不做特别处理,就近原则
MM::print();
}
protected:
string name;
int age;
};
//虚继承 --->菱形继承
class A
{
public:
A(int a) :a(a) {}
protected:
int a;
};
class B :virtual public A
{
public:
B(int a, int b) :A(a), b(b) {}
protected:
int b;
};
class C :virtual public A
{
public:
C(int a, int c) :A(a),c(c) {}
void printC()
{
cout << a << endl;
}
protected:
int c;
};
class D :public C, public B
{
public:
//菱形继承,必须调用祖父的构造函数
D() :B(1, 2), C(3, 4) ,A(999)
{
}
void print()
{
//只有一个a 只有一份
cout << a << endl;
cout << B::a << endl;
cout << C::a << endl;
printC();
}
protected:
};
int main()
{
//不做特别处理,就近原则
//正常对象调用
Girl girl("girl", 18);
girl.print();
MM mm("mm", 28);
mm.print();
//正常的指针调用
//就近原则
Girl* pG = new Girl("newGirl", 19);
pG->print();
pG->MM::print();
MM* pM = new MM("newMM", 29);
pM->print();
//非正常的指针
//1.允许子类对象初始化父类指针
MM* pMM = new Girl("newGirl", 49);
pMM->print(); //父类的
//在没有virtual情况下,看指针类型
//在有virtual情况,看赋值对象
//2.父类对象初始化子类指针,不安全
//Girl* pGirl = new MM("newMM", 29); 错误
//Girl* pGirl = (Girl*)pM;
//pGirl->print(); 引发
D d;
d.print();
return 0;
}
四、构造顺序问题
1.单继承中的构造顺序问题
● 先构造父类的在构造子类的,析构顺序相反
2.多继承中的构造顺序问题
● 任何构造顺序问题都和初始化参数列表无关
● 构造顺序和继承顺序一致
#include <iostream>
using namespace std;
class A
{
public:
A() { cout << "A"; }
~A() { cout << "A" ; }
protected:
};
class B :public A
{
public:
B() { cout << "B"; }
~B() { cout << "B" ; }
};
class C
{
public:
C() { cout << "C"; }
~C() { cout << "C"; }
};
class D
{
public:
D() { cout << "D"; }
~D() {cout << "D";}
};
//构造顺序和继承顺序一致
class F :public C, public A, public D
{
public:
//任何构造顺序问题,都和初始化参数列表无关
F() { cout << "F";}
~F() { cout << "F";}
};
//CADF FDAC
int main()
{
{
B b; //ABBA
}
cout << endl;
F f;
return 0;
}