【漫漫转码路】Day 40 C++ day11

虚函数

基类指针直接指向派生类指针的时候,不用做强制类型转换

B*pb = new B();  //B是A的子类
A*pa = pb;
//例如
class A
{
public:
	A() {};
	~A() {};
public:
	virtual void output() { cout << "这是A\n"; };
};

class B: public A
{
public:
	B() {};
	~B() {};
public:
	virtual void output() { cout << "这是B\n"; };
};
int main()
{
	A* pa = new A();  
	pa->output();

	A* pb = new B();  //B是A的实例,当基类
	pb->output();
	//B *pa2 = new A();  //会报错
}
//显示
这是A
这是B

当声明一个函数是虚函数的时候,使用指针的方式调基类的方法,会自动调用实例的同名虚函数
子类不能调基类的同名虚函数
如果在基类中不声明virtual(虚函数)

//例如
class A
{
public:
	A() {};
	~A() {};
public:
	void output() { cout << "这是A\n"; };  //A中不声明虚函数胡,就是正常函数,则结果会调用A的output()
};

class B: public A
{
public:
	B() {};
	~B() {};
public:
	virtual void output() { cout << "这是B\n"; };
};
int main()
{
	A* pb = new B();
	pb->output();
}
//显示
这是A

根本性原因:可以用于功能的扩充
如果基类声明过虚函数,则子类一律认为使用虚函数

//例如
class A
{
public:
	A() {};
	~A() {};
public:
	virtual void output() { cout << "这是A\n"; };
};

class B: public A
{
public:
	B() {};
	~B() {};
public:
	void output() { cout << "这是B\n"; };  // 子类中不用virtual
};

class C : public B
{
public:
	C() {};
	~C() {};
public:
	void output() { cout << "这是C\n"; };  // 子类中不用virtual
};

int main()
{
	C* pc = new C();
	A* pa = pc;
	B* pb = pc;
	pa->output();
	pb->output();
}
//显示
这是C
这是C

纯虚函数

纯虚函数是一种特殊的虚函数,在许多情况下,在基类中不能对虚函数给出有意义的实现,而把它声明为纯虚函数,它的实现留给该基类的派生类去做。这就是纯虚函数的作用。C++中的纯虚函数,一般在函数名后使用=0作为此类函数的标志。
纯虚函数在子类中一定要有实体;
有纯虚函数的类不能实例化;

//例如
class A
{
public:
	A() {};
	~A() {};
public:
	virtual void output() = 0;  // 纯虚函数
};

class B: public A
{
public:
	B() {};
	~B() {};
public:
	virtual void output() { cout << "这是B\n"; };
};
int main()
{
	B* pb = new B();
	A* pa = pb;
	pa->output();

如果一个类中所有函数都是纯虚函数,则称这个类为接口,这个类就用于扩充
抽象类也叫接口

虚析构函数

正常情况

//例如
class A
{
public:
	A() {};
	~A() { cout << "这是A的析构函数\n"; };
public:
	virtual void output() = 0;  //纯虚函数
};

class B: public A
{
public:
	B() {};
	~B() { cout << "这是B的析构函数\n"; };
public:
	virtual void output() { cout << "这是B\n"; };
};

int main()
{

	B* pb = new B();
	A* pa = pb;
	pa->output();
	delete pa;  //释放pa
}
//显示
这是B
这是A的析构函数

虚析构函数

//例如
class A
{
public:
	A() {};
	virtual ~A() { cout << "这是A的析构函数\n"; };  //将析构函数声明为虚
public:
	virtual void output() = 0;  //纯虚函数
};

class B: public A
{
public:
	B() {};
	virtual ~B() { cout << "这是B的析构函数\n"; };  // 子类不声明virtual也可以
public:
	virtual void output() { cout << "这是B\n"; };
};

int main()
{

	B* pb = new B();
	A* pa = pb;
	pa->output();
	delete pa;  // 释放pa
}
//显示
这是B
这是B的析构函数  // 先释放b,然后释放a
这是A的析构函数

一般在用虚函数的时候,都会用虚析构函数,将子类创建的实例及时释放,防止内存溢出

非常重要

//例如
class A
{
public:
	A() { output(); };  //在A中调output
	virtual ~A() { cout << "这是A的析构函数\n"; };
public:
	virtual void output() { cout << "这是A\n"; };  
};

class B: public A
{
public:
	B() { cout << "这是B的构造函数\n"; };
	~B() { cout << "这是B的析构函数\n"; };
public:
	virtual void output() { cout << "这是B\n"; };
};

int main()
{
	A* pa = new B;  // 此时在创建B的实例的时候,会先执行基类A的构造函数,A的构造函数执行output(),此时,还没有到执行虚函数的时候,所以此时会执行A的output(),然后执行B的构造函数,
}
//显示
这是A
这是B的构造函数

虚函数的应用

在基类中写出公共基类,用虚函数写,作为接口,比如output
然后在子类中创建实例,基类指向子类的实例,用基类调用虚构函数,相当于执行子类的虚构函数
比如两个子类,一个是字符,一个是向量,输出的格式不一样吗,各自写出来同名的虚构函数,然后yoga基类的虚构函数调用,这样可以实现不同的输出

#error会自动编译出错,并将后面的字符打印出来

你可能感兴趣的:(转码,c++,开发语言,改行学it,算法,数据结构)