文章目录
1.继承
对于继承的基础知识点参考:c++继承,下面就不过多阐述。没有记录的必要性
1.1 定义
1.2 基类派生类
1.3 访问控制和继承的方式
1.4 继承中构造与析构调用原则
构造;先构造父类,再构造成员变量,最后构造自己
析构:先析构自己,再构造成员变量,最后析构父类
构造即生成,析构即释放,释放是按生成的相反顺序!
1.5 继承中同名成员变量处理
- 当子类成员变量与父类成员变量同名时
- 子类依然从父类继承同名成员
- 在子类中通过作用域分辨符::进行同名成员区分(在派生类中使用基类的同名成员,显式地使用类名限定符)
- 同名成员存储在内存中的不同位置
#include<iostream>
using namespace std;
class A
{
public:
A(int a = 0, int b = 0)
{
this->a = a;
this->b = b;
cout << "我是爸爸构造"<< endl;
}
~A()
{
cout <<"我是爸爸析构" << endl;
}
void printfB1()
{
cout << "爸爸b=" << b << endl;
}
int get()
{
return b;
}
public:
int a;
int b;
};
class B :public A
{
public:
B(int b = 0, int c = 0)
{
this->b = b;
this->c = c;
cout << "我是儿子构造"<< endl;
}
~B()
{
cout << "我是儿子析构"<< endl;
}
void printfB2()
{
cout <<"儿子b="<< b<< endl;
}
int get()
{
return b;
}
public:
int b;
int c;
};
int main()
{
//同名的成员变量相互独立,而同名的成员函数会发生覆盖。
B b1;
A a1;
cout << "=====" << endl;
//同名成员变量
b1.b = 11;
b1.B::b = 12;
b1.A::b = 22;
b1.printfB1();
b1.printfB2();
cout << "=====" << endl;
//同名成员函数
cout << b1.get()<< endl;//b1.B::get()
cout << b1.B::get()<< endl;
cout << b1.A::get()<< endl;
cout << "=====" << endl;
}
1.6 派生类中的static关键字
1.6.1 静态数据成员
- 基类定义的静态成员, 将被所有的派生类共享。
- 静态数据成员在程序中只有一份拷贝, 由该类型的所有对象共享访问。
- 静态数据成员和普通数据成员一样遵从访问控制原则。
1.6.2 静态成员函数
- 出现在类体外的函数定义不能指定关键字static 。
- 静态成员函数只能访问静态数据成员和静态成员函数。
- 静态成员函数也遵从访问控制原则。
1.6.3 代码
#include<iostream>
using namespace std;
class Base
{
public:
//定义一个静态成员
static int i;
void print()
{
cout << "i: " << i << endl;
}
//静态成员函数只能在类的内部定义
//只能使用静态成员函数和静态数据成员
static void Add1()
{
i++;
}
};
//对静态成员显式地进行初始化,让编译器分配内存空间
int Base::i = 0;
class Derived : public Base
{
public:
void print()
{
cout << "i: " << i << endl;
}
static void Add2()
{
i += 2;
}
};
int main()
{
//在使用时,所有的基类和派生类对象使用的是同一个静态成员
Base b1;
b1.i = 2;
b1.print();
Derived d1;
d1.print();
d1.i = 5;
d1.print();
b1.print();
b1.Add1();
b1.print();
d1.Add2();
b1.print();
d1.print();
return 0;
}
1.7 多继承带来的二义性
1.7.1 什么是多重继承的二义性
如果一个派生类从多个基类派生,而这些基类又有一个共同的基类,则在对该基类中声明的成员变量进行访问时,可能产生二义性
1.7.2 解决办法
#include <iostream>
using namespace std;
class A{
public:
int a;
void f(){
cout << "A.f() " << endl;
};
};
class B1 : public A{
//class B1 : virtual public A{//【解决办法1】虚继承
public:
int b1;
};
class B2 : public A{
//class B2 : virtual public A{
public:
int b2;
};
class C : public B1, public B2{
public:
int c1;
void f(){//【解决办法3】同名覆盖
B1::f();
cout << "C.f() " << endl;
}
};
int main(){
C c1;
c1.b1 = 100;
c1.b2 = 200;
c1.c1 = 300;
//【解决办法1】虚继承
// c1.a = 500; //继承的二义性 和 虚继承解决方案
// 【解决办法2】类名限定
cout << c1.B1::a << endl;
cout << c1.B2::a << endl;
// 【解决办法3】同名覆盖
c1.f();
return 0;
}
2.多态
2.1 静态多态
静态多态是编译器在编译期间完成的,编译器根据函数实参的类型(可能会进行隐式类型的转换),可推断出要调用哪个函数,如果有对应的函数就调用该函数,否则出现编译错误
2.2 动态多态
动态多态的实现条件
- 继承
- 基类中必须包含虚函数,并且派生类一定要对基类中的虚函数进行重写
- 通过基类对象的指针或引用调用虚函数
#define _CRT_SECURE_NO_WARNING 1
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
using namespace std;
class FittingRoom
{
public:
void GoToManFittingRoom()
{
cout<<"Man--->Please go to left"<<endl;
}
void GoToWomanFittingRoom()
{
cout<<"Woman--->Please go to right"<<endl;
}
};
class Person
{
public:
virtual void GotoFitttingRoom(FittingRoom& ft) = 0;
};
class Man:public Person
{
public:
virtual void GotoFitttingRoom(FittingRoom& ft)
{
ft.GoToManFittingRoom();
}
};
class Woman:public Person
{
public:
virtual void GotoFitttingRoom(FittingRoom& ft)
{
ft.GoToWomanFittingRoom();
}
};
void TestFittingRoom()
{
FittingRoom ft;
Person* p = NULL;
for(int i = 1; i <= 10; ++i)
{
if( (rand()%i) & 0x01)
p = new Man;
else
p = new Woman;
p->GotoFitttingRoom(ft);
delete p;
Sleep(1000);
}
}
int main()
{
TestFittingRoom();
return 0;
}