其他知识
关于NULL 的问题
建议以后还是都用nullptr替代NULL吧。
https://blog.csdn.net/gcs6564157/article/details/75045949pragma once
pragma once是一个比较常用的C/C++杂注,只要在头文件的最开始加入这条杂注,就能够保证头文件只被编译一次。
- 父类里面没有默认的构造函数,那么子类里面也不能有默认的构造函数
例子1 继承的基本使用
父类 Plane 两个类: 一个是头文件 一个是源文件
#pragma once
#include <string>
class Plane
{
public:
Plane();
Plane(std::string name, int year);
~Plane();
void fly();
void land();
void printf();
protected:
std::string name;
int year;
};
源文件
#include <Plane.h>
#include <iostream>
//#include <string>
using namespace std;
Plane::Plane() :name("F-22"), year(2010)
{
cout << "Plane 无参(默认)的构造函数: 名字:" << name << " 生产年代:" << year << endl;
}
Plane::Plane(std::string name, int year) :name(name), year(year)
{
cout << "Plane 的构造函数" << name << year << endl;
}
Plane::~Plane()
{
cout << "Plane 的析构函数" << endl;
}
void Plane::fly(){
cout << "Plane 的fly函数" << endl;
}
void Plane::land(){
cout << "Plane 的land函数" << endl;
}
void Plane::printf(){
cout << "Plane 的printf函数" << endl;
}
子类 两个文件 头文件 源文件
#pragma once
#include <Plane.h>
class Jet : public Plane
{
public:
Jet();
Jet(std::string name, int year);
~Jet();
private:
};
这里继承 使用: 来继承
源文件
#include <Jet.h>
#include <iostream>
using namespace std;
Jet::Jet()
{
cout << "Jet 无参(默认)数的构造函数 名字: " << name << " 生产年代:" << year << endl;
}
Jet::Jet(std::string name, int year)
{
cout << "Jet 参(默认)的构造函数: 名字:" << name << " 生产年代:" << year << endl;
}
Jet::~Jet()
{
cout << "Jet 的析构函数" << endl;
}
主类 main 调用
#include <Plane.h>
#include <iostream>
#include <string>
#include <Jet.h>
using namespace std;
void func(){
Jet jet;
jet.fly();
}
void main(){
func();
system("pause");
}
打印结果 :
Plane 无参(默认)的构造函数: 名字:F-22 生产年代:2010
Jet 无参(默认)数的构造函数 名字: F-22 生产年代:2010
Plane 的fly函数
Jet 的析构函数
Plane 的析构函数
请按任意键继续. . .
上面 jet.fly() 调用的是父类的方法, 没有在子类里声明任何方法
如果在子类 Jet里面定义和父类Plane里面相同的方法 那么调用的时候就是子类的方法.重写
如果已经重写了 那么
可以看到调用顺序
创建的时候 先调用父类的构造函数 释放时 先调用子类的析构函数
已经重写了父类的函数,但想调用父类的函数怎么调用
jet.Plane :: fly();
这样就调用了父类的函数.
下面调用的是父类的函数还是子类的函数
//派生类赋给父类
Plane *pl = &jet//指针
pl->fly();
Plane &p2 = jet;//对象
p2.fly();
结果调用的是父类的函数.
重载和重写
重载 参数不同函数名相同
重写 都相同
例子2 继承的二义性.多继承
class A
{
public:
string name;
};
class A1: public A
{
};
class A2 : public A
{
};
//多继承的二义性 :只能显示使用根属性
//多继承用逗号分隔
class B : public A1, public A2
{
};
调用:
B b;
//b :: name = "test";// 如果直接调用会报错, 不知道使用的是A1还是A2的 name 这就是继承的二义性
b.A1::name = "nameA1"; //只能显示调用
b.A2::name = "nameA2";
如果想给父类的name赋值 ?
虚继承 virtual
// virtual 虚继承 : 解决路径不明确的问题,使多个继承的同名成员时候 只有一份拷贝
两个派生类
class A1:virtual public A
{
};
class A2 : virtual public A
{
};
调用:
B b;
b : name = "test";// 如果直接调用 不知道使用的是A1还是A2的 name 继承的二义性
b.A1::name = "nameA1"; //只能显示调用
b.A2::name = "nameA2";
继承类型
当一个类派生自基类,该基类可以被继承为 public、protected 或 private 几种类型。继承类型是通过上面讲解的访问修饰符 access-specifier 来指定的。
我们几乎不使用 protected 或 private 继承,通常使用 public 继承。
详细看这里 http://www.runoob.com/cplusplus/cpp-inheritance.html
问题 父类的指针 指向 一个子类对象 导致内存泄露
//用父类的指针来new一个子类的对象
Plane *jet = new Copter();
//调用了子类中的虚函数
jet->land();
//回收
delete jet;
jet = nullptr; //这种情况存在内存泄漏的可能
结果调用了父类的析构函数 但是没有调用子类的析构函数. 这个时怎么解决.
解决: 需要在父类的析构函数中加上virtual关键字
解析: 父类加上virtual关键字,那么子类里面默认也是加上了virtual.
相似代码参考
https://www.jianshu.com/p/c9055d8f66bc
纯虚函数
纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加”=0”
virtual void funtion1()=0
实际就是定义个接口
参考资料
http://www.runoob.com/w3cnote/cpp-virtual-function.html