/**
* 继承:公共继承/保护继承/私有继承
* class 子类:继承方式 父类
*/
//public 继承,除了父类私有,其他的都直接原有权限拿来。
//protected 继承,除了父类私有,其他权限都是保护拿来。
//private 继承,除了父类私有,其他的都是私有拿来。
class BasePage {
public:
void baseInfo() {
cout << "公共部分" << endl;
}
int m_Pub;
protected:
int m_pro;
private:
int m_pri;
};
class Son1 : public BasePage {
public:
Son1() {
m_Pub = 100;//public 继承过来。
m_pro = 100;//protected 继承过来。
// m_pri = 100;//不能访问
}
int m_son1;
};
class Son2 : protected BasePage {
public:
Son2() {
m_Pub = 100;//protected 继承过来。
m_pro = 100;//protected 继承过来。
// m_pri = 100;//不能访问
}
};
class Son3 : private BasePage {
public:
Son3() {
m_Pub = 100;//private 继承过来。
m_pro = 100;//private 继承过来。
// m_pri = 100;//不能访问
}
};
class Java : public BasePage {
public:
void content() {
cout << "Java特有部分" << endl;
}
};
class CPP : public BasePage {
public:
void content() {
cout << "CPP特有部分" << endl;
}
};
int main() {
Java java;
java.baseInfo();
java.content();
cout << "__________________" << endl;
CPP cpp;
cpp.baseInfo();
cpp.content();
Son1 son1;
son1.m_Pub;//这里只能使用public 部分。
Son2 son2;//在类外都无法访问。因为是protected
Son3 son3;//在类外都无法访问。因为是private
cout << sizeof (son1)<<endl;//结果16,说明所有的非静态属性继承过来的内容。属于子类。包含私有。只是私有的隐藏起来。
cout << sizeof (son2)<<endl;//结果12,说明所有的非静态属性继承过来的内容。属于子类。包含私有。只是私有隐藏起来。
return 0;
}
//继承中构造和析构函数的执行顺序。
//构造的时候,先有父类构造,析构与之相反。
//继承中同名的成员处理。
class Base {
public:
Base() {
m_A = 40;
}
int m_A;
void func(int a) {
cout << "Base (int a)func" << endl;
}
void func() {
cout << "Base func" << endl;
}
};
class Son : public Base {
public:
Son() {
m_A = 10;
}
int m_A;
void func() {
cout << "Son func" << endl;
}
};
int main() {
Son son;
cout << "子类的值:" << son.m_A << endl;
Base base;
cout << "父类的值:" << base.m_A << endl;
cout << "父类的值:" << Base().m_A << endl;
//如果想通过子类对象,获取到父类的成员属性。
cout << "父类的值:" << son.Base::m_A << endl;
son.func();
//下面编译报错。因为如果子类实现了同名的成员函数,那么就会隐藏父类所有的同名函数的实现。
//如果想调用父类的函数,那么只有加作用域。
// son.func(100);
son.Base::func(100);
return 0;
}
//继承中的静态成员处理,下面是成员属性。成员函数也是如此。。
//多重继承。class 子类:继承方式 父类1,继承方式 父类2. 如果出现同名属性,则用作用域进行区分。
class Base{
public:
static int m_A;
};
int Base::m_A = 200; //对父类的静态成员进行初始化。
class Son : public Base{
public:
static int m_A;
};
int Son::m_A = 100;//对子类的静态成员属性进行初始化。
int main(){
Son son;
cout << "子类"<<son.m_A<<endl;
cout << "父类"<<son.Base::m_A<<endl;
cout << "-----------------"<<endl;
cout << "子类"<<Son::m_A<<endl;
cout << "父类"<<Base::m_A<<endl;
cout << "父类"<<Son::Base::m_A<<endl;
return 0;
}
//菱形继承,也称为多继承。会copy两份数据。造成浪费。
//解决这一问题,通过virtual 关键字进行继承。也称为虚继承。
//如果不加virtual那么就会继承两份数据过来。
class Animal{//动物
public :
int m_Age;
};
class Sheep:virtual public Animal{//羊
public:
Sheep(){
m_Age = 100;
}
};
class Camel:virtual public Animal{//驼
public:
Camel(){
m_Age = 200;
}
};
class SheepCamel:public Sheep,public Camel{};//羊驼
int main(){
SheepCamel sheepCamel;
cout << sheepCamel.m_Age<<endl;
cout << sheepCamel.Sheep::m_Age<<endl;
cout << sheepCamel.Camel::m_Age<<endl;
return 0;
}
/**
* 动态多态:
* 1.继承
* 2.子类要重写父类的虚函数。(返回值,函数名,参数列表完全相同)
* 3.父类的指针或者引用指向子类的对象。
*/
//动物基类
class Animal {
public:
virtual void speak() { //如果这里不是虚函数,那么就是前绑定,不会形成多态。绑定为基类的方法执行。如果声明为virtual,形成多态的必要条件之一。
cout << "动物在说话" << endl;
}
};
//猫类
class Cat : public Animal {
public:
void speak() {
cout << "小猫在说话" << endl;
}
};
// 这里有一个说话的方法
void doSpeak(Animal &a) {
a.speak();
}
void test() {
Cat cat;
doSpeak(cat);
}
void test01() {
//如果Animal 中没有virtual,那么就是一个空类,sizeof(Animal)=1
//如果Animal 中有virtual,那么就是一个空类,sizeof(Animal)=8,多了地址(指针)
cout << sizeof(Animal) << endl;
}
int main() {
test();
test01();
return 0;
}
/**
*普通写法和多态写法实现计算器
*/
//这里涉及到一个开闭原则:对扩展开放,对修改关闭。
//传统写法
class Caculator {
public:
Caculator(int a, int b) : m_Num1(a), m_Num2(b) {
}
int getResult(string oper) {
if ("+" == oper) {
return m_Num1 + m_Num2;
} else if ("-" == oper) {
return m_Num1 - m_Num2;
} else if ("*" == oper) {
return m_Num1 * m_Num2;
}
}
private :
int m_Num1;
int m_Num2;
};
class AbstractCaculator {
public:
virtual int getResult() {
}
int m_Num1;
int m_Num2;
};
//+法
class AddCaculator : public AbstractCaculator {
public:
int getResult() {
return m_Num1 + m_Num2;
}
};
//-法
class SubCaculator : public AbstractCaculator {
public:
int getResult() {
return m_Num1 - m_Num2;
}
};
//传统形式的计算器写法测试
void test() {
Caculator caculator(2, 3);
cout << caculator.getResult("+") << endl;
}
//多态实现测试
void test01() {
AbstractCaculator *abstractCaculator = new AddCaculator(); //加法
abstractCaculator->m_Num1 = 10;
abstractCaculator->m_Num2 = 5;
int ret = abstractCaculator->getResult();
cout << ret << endl;
delete abstractCaculator;
abstractCaculator = new SubCaculator(); //减法
abstractCaculator->m_Num1 = 10;
abstractCaculator->m_Num2 = 5;
ret = abstractCaculator->getResult();
cout << ret << endl;
if (abstractCaculator != NULL) {
delete abstractCaculator;
abstractCaculator = NULL;
}
}
int main() {
//test();
test01();
return 0;
}
/**
* 抽象类和纯虚函数:
* 只要有一个纯虚函数的类就是抽象函数。
* 抽象类无法实例化对象,子类必须重写纯虚函数,否则也是抽象类。
* 纯虚函数语法:virtual 返回值 函数名() = 0;
*/
class Base{//这是一个抽象类,不能被实例化。继承该类的子类需要实现纯虚函数。否则也是抽象函数。
public:
virtual void func() = 0;//这是一个纯虚函数。
};
class Son:public Base{
public:
void func(){//子类需要实现这个纯虚函数。
cout<<"Son func exec"<<endl;
}
};
int main(){
// Base base;//编译报错,因为抽象函数不能被实例化
Son son;
son.func();
return 0;
}
/**
*虚析构函数 和纯析构函数
*/
//适用场景:如果子类的属性开辟在堆中,那么父类无法释放子类中的内存。
//都是用来解决子类属性申请在堆空间。无法释放内存的问题。
class Animal{
public:
virtual void speak() = 0;
// virtual ~Animal() = 0;
virtual ~Animal(){
cout << "动物析构函数函数被调用。"<<endl;
}
};
//Animal::~Animal() {
// cout << "动物析构函数函数被调用。"<<endl;
//}
class Cat:public Animal{
public:
Cat(string name){
cout << "猫的构造函数函数被调用。"<<endl;
m_Name = new string(name);
}
void speak(){
cout << "小猫在叫"<<endl;
}
~Cat(){
cout << "猫的析构函数函数被调用。"<<endl;
if (m_Name != NULL){
delete m_Name;
m_Name = NULL;
}
}
string *m_Name;
};
int main(){
Animal *animal = new Cat("Tom");
animal->speak();
return 0;
}
c++教程2021-6-18学习笔记
最新推荐文章于 2024-05-02 22:07:44 发布