本博文是学习黑马程序员C++视频时做的笔记,记录一下只是方便温故知新,不做其他用途。
C++面向对象三大特性:封装、继承、多态。
一、封装
封装:隐藏对象的属性和实现细节,仅对外公开接口和对象进行交互,将数据和操作数据的方法进行有机结合。 封装的意义: (1)将属性和行为作为整体,表现生活中的事物 (2)将属性和行为加以权限控制
1.1 类的定义
语法:class 类名 {访问权限:属性和行为}。
#include<iostream>
using namespace std;
class Student{
public:
string name;
int s_id;
void ShowStudent()
{
cout<<"name:"<<name<<" student_id="<<s_id<<endl;
}
};
int main()
{
Student s1;
s1.name = "张三";
s1.s_id = 001;
s1.ShowStudent();
return 0;
}
1.2 访问权限
把属性和行为放在不同的权限下,加以控制。 (1)public:公共权限——成员 类内可以访问,类外可以访问。 (2)protected:保护权限——成员 类内可以访问,类外不可访问,儿子可以访问父亲中的保护内容。 (3)private:私有权限——成员 类内可以访问,类外不可访问。
#include<iostream>
#include<string>
using namespace std;
class Person
{
public:
string m_name;
protected:
string m_car;
private:
int m_password;
public:
void func()
{
m_name="张三";
m_car = "小车";
m_password=123456;
cout<<m_name<<m_car<<m_password<<endl;
}
};
int main()
{
Person p1;
p1.m_name="王二麻子";
p1.func();
return 0;
}
1.3 class和struct区别
类内都可以访问;类外,class 默认权限为私有,struct默认权限为公有
#include<iostream>
#include<string>
using namespace std;
class C1{
int m_A;
};
struct S1{
int m_A;
};
int main()
{
C1 c1;
S1 s1;
s1.m_A = 100;
return 0;
}
1.4 成员属性私有化
优点: (1)可以控制读写权限 (2)对于写可以检测数据的有效性
例子中,将所有变量都在设置为私有,然后在public里面分别添加各个对应的函数就可以实现各种权限。
#include<iostream>
#include<string>
using namespace std;
class Person
{
private:
string m_name;
int m_age;
string m_lover;
public:
void setname(string name)
{
m_name=name;
}
string showname()
{
return m_name;
}
int readAge()
{
m_age=23;
return m_age;
}
void setlover(string lover)
{
m_lover = lover;
}
};
int main()
{
Person p1;
p1.setname("王五");
cout<<p1.showname()<<endl;
cout<<p1.readAge()<<endl;
p1.setlover("ccc");
}
二、对象特性
2.1构造函数和析构函数
构造函数:用于创建对象时为对象的成员属性赋值,构造函数由编译器自动调用。 语法:类名(){} (1)没有返回值 也不写void; (2)函数名称与类名称相同; (3)构造函数可以有参数,因此可以发生重载; (4)创建对象时,会自动调用构造函数,无需手动调用,而且只会调用一次。
析构函数:用于对象销毁前系统自动调用,执行一些清理工作。 语法:~类名(){} (1)没有返回值 也不写void; (2)函数名称与类名称相同,需要加上符号~; (3)构造函数不可以有参数,因此不可以发生重载; (4)对象销毁前,会自动调用构造函数,无需手动调用,而且只会调用一次。
#include<iostream>
#include<string>
using namespace std;
class Person
{
private:
string m_name;
public:
Person()
{
cout<<"无参构造函数!"<<endl;
}
Person(int a)
{
m_name=a;
cout<<"有参构造函数!"<<endl;
}
Person(const Person &p)
{
cout<<"拷贝构造函数!"<<endl;
}
~Person()
{
cout<<"析构函数!"<<endl;
}
};
void test()
{
Person p1;
Person p2(10);
Person p3(p2);
}
int main()
{
test();
return 0;
}
深拷贝和浅拷贝区别 深拷贝:在堆区重新申请空间,进行拷贝操作; 浅拷贝:简单的赋值拷贝操作。
#include<iostream>
#include<string>
using namespace std;
class Person
{
public:
Person()
{
cout << "无参构造函数" << endl;
}
Person(int age ,int height)
{
cout << "有参构造函数" << endl;
m_age = age;
m_height = new int(height);
}
Person(const Person& p)
{
cout << "拷贝构造函数" << endl;
m_age = p.m_age;
m_height = new int(*p.m_height);
}
~Person() {
if (m_height != NULL)
{
delete m_height;
m_height = NULL;
}
cout<<"析构函数调用"<<endl;
}
public:
int m_age;
int* m_height;
};
void test()
{
Person p1(26, 172);
Person p2(p1);
cout << "p1的年龄= " << p1.m_age << " 身高= " << *p1.m_height << endl;
cout << "p2的年龄=" << p2.m_age << " 身高= " << *p2.m_height << endl;
}
int main() {
test();
return 0;
}
2.2 初始化列表
语法:构造函数():属性1,属性2…{}
#include<iostream>
#include<string>
using namespace std;
class Person
{
public:
Person(int a,int b,int c):m_A(a),m_B(b),m_C(c) {}
void PrintPerson()
{
cout << "m_A= " <<m_A <<endl;
cout << "m_B= " <<m_B <<endl;
cout << "m_C= " <<m_C <<endl;
}
private:
int m_A;
int m_B;
int m_C;
};
int main() {
Person p(1,2,3);
p.PrintPerson();
return 0;
}
2.3 类对象作为类成员
类中的成员可以是另一个类的对象。
#include<iostream>
#include<string>
using namespace std;
class Phone
{
public:
Phone(string Pname)
{
m_Pame = Pname;
cout<<"Phone 类"<<endl;
}
~Phone(){
cout<<"Phone 析构"<<endl;
}
string m_Pame;
};
class Person
{
public:
Person(string name,string pName):m_Name(name),m_Phone(pName){
cout<<"Person 类"<<endl;
}
~Person(){
cout<<"Person 析构"<<endl;
}
string m_Name;
Phone m_Phone;
};
void test()
{
Person p("张三","xiaomi");
cout<<p.m_Name<<"has a "<<p.m_Phone.m_Pame<<endl;
}
int main()
{
test();
return 0;
}
2.4 静态成员函数
所有对象共享一个函数 静态成员函数只能访问静态成员变量
#include<iostream>
using namespace std;
class Student{
public:
static void func()
{
m_A = 100;
cout<<"static void func:"<<endl;
}
static int m_A;
int m_B;
};
int Student::m_A;
void test01(){
Student s1;
s1.func();
Student::func();
}
int main()
{
test01();
return 0;
}
2.5 C++对象模型和this指针
2.5.1 成员变量成员函数分开存储
#include<iostream>
#include<string>
using namespace std;
class Person
{
int m_name;
static int m_b;
void func(){}
};
void test01()
{
Person p;
cout<<"the size of p is:"<<sizeof(p)<<endl;
}
int main()
{
test01();
return 0;
}
2.5.2 this指针概念
1 概念:this指针指向被调用的成员函数所属的对象。 2 特点: (1)this指针隐含在每一个非静态成员函数内, (2)this指针不需要定义直接使用 3 用途: (1)当形参和成员变量同名时,可用this指针来区分; (2)返回对象本身return *this
#include<iostream>
#include<string>
using namespace std;
class Person
{
public:
Person(int age)
{
this->age = age;
}
Person& PersonAddAge(Person &p)
{
this->age += p.age;
return *this;
}
int age;
};
void test01()
{
Person p1(18);
cout<<"p1的年龄"<<p1.age<<endl;
}
void test02()
{
Person p1(10);
Person p2(10);
p2.PersonAddAge(p1).PersonAddAge(p1).PersonAddAge(p1);
cout<<"p2的年龄"<<p2.age<<endl;
}
int main()
{
test02();
return 0;
}
2.5.3 空指针访问成员函数(判定this指针是否为空来解决)
空指针调用普通成员函数,如果使用到了this指针(访问非静态成员变量),程序会崩溃;如果没有使用到this指针,程序不会崩溃。
#include<iostream>
#include<string>
using namespace std;
class Person
{
public:
void showClassName(){
cout<<"this is Person class"<<endl;
}
void showClassage(){
if(this == NULL){
return;
}
cout<<"this is class age"<< this->m_age<<endl;
}
int m_age;
};
void test01()
{
Person *p1 = NULL;
p1->showClassName();
p1->showClassage();
}
int main()
{
test01();
return 0;
}
2.5.4 const修饰成员函数(常函数和常对象)
1、常函数( void func() const {…} ) (1)成员函数后加const变成常函数; (2)常函数内不可以修改成员属性; (3)成员属性声明的时候加关键字mutable后,在常函数中就可以修改。 2、常对象 (1)声明对象的时候在前面加上const即可变成常对象; (2)常对象只能访问常函数,普通函数不能被访问。
#include<iostream>
#include<string>
using namespace std;
class Person
{
public:
Person(){
m_a = 0;
m_B = 0;
}
void showPerson() const
{
this->m_B = 100;
cout<<"常函数"<<endl;
}
void func1()
{
cout<<"普通函数"<<endl;
}
public:
int m_a;
mutable int m_B;
};
void test01()
{
Person p1;
p1.showPerson();
p1.func1();
p1.m_a = 100;
p1.m_B = 100;
}
void test02()
{
const Person p2;
p2.showPerson();
p2.m_B = 100;
}
int main()
{
test01();
test02();
return 0;
}
三、 C++友元
友元的作用就是令全局函数或者类,可以访问另一个类。
3.1 全局函数做友元
例子中的void goodGay(Buiding *buiding)为全局函数,friend void goodGay(Buiding *buiding)为友元,可以访问Buiding中的私有成员。
#include<iostream>
#include<string>
using namespace std;
class Buiding
{
friend void goodGay(Buiding *buiding);
public:
Buiding()
{
m_sintingroom="客厅";
m_bedroom = "卧室";
}
public:
string m_sintingroom;
private:
string m_bedroom;
};
void goodGay(Buiding *buiding)
{
cout<<"goodGay正在访问:"<<buiding->m_sintingroom<<endl;
cout<<"goodGay正在访问:"<<buiding->m_bedroom<<endl;
}
void test01()
{
Buiding Buiding;
goodGay(&Buiding);
}
int main()
{
test01();
return 0;
}
3.2 类做友元
例子中在Building类中添加friend class GoodGay;这一句,实现类做友元,GoodGay类可以访问Building类中的私有内容。
#include<iostream>
using namespace std;
#include<string>
class Building;
class GoodGay
{
public:
GoodGay();
public:
void visit();
Building* building;
};
class Building
{
friend class GoodGay;
public:
Building();
public:
string m_SittingRoom;
private:
string m_BedRoom;
};
Building::Building()
{
m_SittingRoom = "客厅";
m_BedRoom = "卧室";
}
GoodGay::GoodGay()
{
building = new Building;
}
void GoodGay::visit()
{
cout << "好基友类正在访问:" << building->m_SittingRoom << endl;
cout << "好基类友正在访问:" << building->m_BedRoom << endl;
}
void test01()
{
GoodGay g;
g.visit();
}
int main()
{
test01();
return 0;
}
3.3 成员函数做友元
例子中friend void goodGay::visit1()这句,实现了让基友visit1可以访问卧室和客厅,基友visit2()只能访问客厅。
#include<iostream>
#include<string>
using namespace std;
class Building;
class goodGay
{
public:
goodGay();
void visit1();
void visit2();
private:
Building * building;
};
class Building
{
friend void goodGay::visit1();
public:
Building();
public:
string m_sittingroom;
private:
string m_bedroom;
};
Building::Building()
{
this->m_bedroom = "卧室";
this->m_sittingroom = "客厅";
}
goodGay::goodGay()
{
building = new Building;
}
void goodGay::visit1()
{
cout << "基友visit1正在" << this->building->m_sittingroom << endl;
cout << "基友visit1正在" << this->building->m_bedroom << endl;
}
void goodGay::visit2()
{
cout << "基友visit2正在" << this->building->m_sittingroom << endl;
}
void test01()
{
goodGay gg;
gg.visit1();
gg.visit2();
}
int main()
{
test01();
return 0;
}
四、运算符重载
概念:对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型。
4.1 加号运算符重载
作用:实现两个自定义数据类型相加的运算。 主要包括: (1)成员函数重载+号:Person p3 = p1.operator+(p2); (2)全局函数重载+号:Person p3 = operator+(p1,p2);
#include<iostream>
#include<string>
using namespace std;
class Person{
public:
int m_A;
int m_B;
};
Person operator+(Person &p1,Person &p2)
{
Person temp;
temp.m_A = p1.m_A + p2.m_A;
temp.m_B = p2.m_B + p2.m_B;
return temp;
}
Person operator+(Person &p1,int num)
{
Person temp;
temp.m_A = p1.m_A + num;
temp.m_B = p1.m_B + num;
return temp;
}
void test01(){
Person p1;
p1.m_A = 10;
p1.m_B = 10;
Person p2;
p2.m_A = 10;
p2.m_B = 10;
Person p3 = operator+(p1,p2);
Person p4 = p1 + 100;
cout<<"p3.m_A = "<<p3.m_A<<endl;
cout<<"p3.m_B = "<<p3.m_B<<endl;
cout<<"p4.m_A = "<<p4.m_A<<endl;
cout<<"p4.m_B = "<<p4.m_B<<endl;
}
int main()
{
test01();
return 0;
}
4.2 左移运算符重载
作用:输出自定义数据类型。
#include"iostream"
using namespace std;
class Person
{
friend ostream & operator<<(ostream &out,Person &p);
public:
Person(int a,int b)
{
this->m_A = a;
this->m_B = b;
}
private:
int m_A;
int m_B;
};
ostream & operator<<(ostream &out,Person &p)
{
out<<"m_A="<<p.m_A<<" m_B="<<p.m_B;
return out;
}
void test01()
{
Person p(10,10);
cout<<p<<" Hello world!"<<endl;
}
int main()
{
test01();
return 0;
}
4.3 递增运算符重载
#include <iostream>
using namespace std;
class MyInteger {
friend ostream &operator<<(ostream &cout, MyInteger myint);
public:
MyInteger()
{
m_Num = 0;
}
MyInteger &operator++()
{
m_Num++;
return *this;
}
MyInteger operator++(int)
{
MyInteger temp = *this;
m_Num++;
return temp;
}
private:
int m_Num;
};
ostream &operator<<(ostream &cout, MyInteger myint)
{
cout<<myint.m_Num;
return cout;
}
void test01()
{
MyInteger myint;
cout<<++myint<<endl;
}
void test02()
{
MyInteger myint;
cout<<myint++<<endl;
}
int main()
{
test01();
test02();
return 0;
}
4.4 赋值运算符重载
#include <iostream>
using namespace std;
class Person
{
public:
Person(int age)
{
m_Age = new int(age);
}
int *m_Age;
~Person()
{
if (m_Age != NULL)
{
delete m_Age;
m_Age = NULL;
}
}
Person& operator=(Person &p)
{
if (m_Age != NULL)
{
delete m_Age;
m_Age = NULL;
}
m_Age = new int(*p.m_Age);
return *this;
}
};
void test01()
{
Person p1(18);
Person p2(20);
Person p3(30);
p3 = p2 = p1;
cout << "p1的年龄为: " << *p1.m_Age << endl;
cout << "p2的年龄为: " << *p2.m_Age << endl;
cout << "p3的年龄为: " << *p3.m_Age << endl;
}
int main()
{
test01();
return 0;
}
4.5 关系运算符重载
#include<iostream>
#include <stdio.h>
#include <string>
using namespace std;
class Person {
public:
Person (string name,int age)
{
m_Name= name;
m_Age = age;
}
bool operator==(Person &p)
{
if(this->m_Name==p.m_Name && this->m_Age ==p.m_Age)
{
return true;
}
else
{
return false;
}
}
string m_Name;
int m_Age;
};
void test01(){
Person p1("王二",18);
Person p2("王二",19);
if(p1==p2)
{
cout<<"相等";
}
else
{
cout <<"不相等";
}
}
int main(){
test01();
return 0;
}
4.6 函数调用运算符重载
函数调用运算符()可以重载,由于重载后使用的方式非常像函数的调用,称为仿函数。
#include <iostream>
#include <stdio.h>
using namespace std;
class MyPrint
{
public:
void operator()(string test)
{
cout <<test <<endl;
}
};
void test01(){
MyPrint myprint ;
myprint("Hello World!");
}
class MyAdd
{
public:
int operator()(int num1 ,int num2)
{
return num1+num2;
}
};
void test02()
{
MyAdd myadd;
int sum = myadd(100,200);
cout << "sum="<<sum<<endl;
cout <<MyAdd()(100,100);
}
int main(){
test01();
test02();
return 0;
}
五、继承
继承是面向对象的三大特性之一。利用继承的方法可以有效减少重复代码。
5.1 继承的基本语法
语法:class 子类:继承方式 父类 class jpage : public page
#include <iostream>
using namespace std;
class basepage
{
public:
void show()
{
cout << "基础界面" << endl;
}
};
class javapage : public basepage
{
public:
void javashow()
{
cout << "java界面" << endl;
}
};
class cpppage : public basepage
{
public :
void cppshow()
{
cout << "cpp界面" << endl;
}
};
class pythonpage : public basepage
{
public:
void pythonshow()
{
cout << "python界面" << endl;
}
};
void test01(){
javapage jav;
jav.show();
jav.javashow();
cout << "**************" << endl;
cpppage cp;
cp.show();
cp.cppshow();
cout << "**************" << endl;
pythonpage py;
py.show();
py.pythonshow();
cout << "**************" << endl;
}
int main()
{
test01();
return 0;
}
5.2 继承方式
语法: class 子类 : 继承方式 父类 方式: 公共继承、保护继承、私有继承
#include <iostream>
using namespace std;
class Base1
{
public:
int m_A;
protected:
int m_B;
private:
int m_C;
};
class Son1 :public Base1
{
public:
void func()
{
m_A;
m_B;
}
};
void test01()
{
Son1 s1;
s1.m_A = 100;
}
class Base2
{
public:
int m_A;
protected:
int m_B;
private:
int m_C;
};
class Son2:protected Base2
{
public:
void func()
{
m_A;
m_B;
}
};
void test02()
{
Son2 s;
}
class Base3
{
public:
int m_A;
protected:
int m_B;
private:
int m_C;
};
class Son3:private Base3
{
public:
void func()
{
m_A;
m_B;
}
};
void test03()
{
Son3 s;
}
class GrandSon3 :public Son3
{
public:
void func()
{
}
};
int main(){
return 0;
}
5.3 继承中的对象模型
#include <iostream>
using namespace std;
class Base
{
public:
int m_A;
protected:
int m_B;
private:
int m_C;
};
class Son :public Base
{
public:
int m_D;
};
void test01()
{
cout << "sizeof Son = " << sizeof(Son) << endl;
}
int main() {
test01();
return 0;
}
5.4 继承中的构造和析构顺序
#include <iostream>
using namespace std;
class Base
{
public:
Base()
{
cout << "Base构造函数!" << endl;
}
~Base()
{
cout << "Base析构函数!" << endl;
}
};
class Son : public Base
{
public:
Son()
{
cout << "Son构造函数!" << endl;
}
~Son()
{
cout << "Son析构函数!" << endl;
}
};
void test01()
{
Son s;
}
int main() {
test01();
return 0;
}
5.5 继承中同名成员处理方式
#include <iostream>
using namespace std;
class Base {
public:
Base()
{
m_A = 100;
}
void func()
{
cout << "Base - func()调用" << endl;
}
void func(int a)
{
cout << "Base - func(int a)调用" << endl;
}
public:
int m_A;
};
class Son : public Base {
public:
Son()
{
m_A = 200;
}
void func()
{
cout << "Son - func()调用" << endl;
}
public:
int m_A;
};
void test01()
{
Son s;
cout << "Son下的m_A = " << s.m_A << endl;
cout << "Base下的m_A = " << s.Base::m_A << endl;
s.func();
s.Base::func();
s.Base::func(10);
}
int main() {
test01();
return 0;
}
5.6 继承中同名静态成员处理方式
#include <iostream>
using namespace std;
class Base {
public:
static void func()
{
cout << "Base - static void func()" << endl;
}
static void func(int a)
{
cout << "Base - static void func(int a)" << endl;
}
static int m_A;
};
int Base::m_A = 100;
class Son : public Base {
public:
static void func()
{
cout << "Son - static void func()" << endl;
}
static int m_A;
};
int Son::m_A = 200;
void test01()
{
cout << "通过对象访问: " << endl;
Son s;
cout << "Son 下 m_A = " << s.m_A << endl;
cout << "Base 下 m_A = " << s.Base::m_A << endl;
cout << "通过类名访问: " << endl;
cout << "Son 下 m_A = " << Son::m_A << endl;
cout << "Base 下 m_A = " << Son::Base::m_A << endl;
}
void test02()
{
cout << "通过对象访问: " << endl;
Son s;
s.func();
s.Base::func();
cout << "通过类名访问: " << endl;
Son::func();
Son::Base::func();
Son::Base::func(100);
}
int main() {
test01();
test02();
return 0;
}
5.7 多继承语法
C++中允许一个类继承多个类 语法:class 子类:继承方式 父类1,继承方式 父类2… 多继承中可能会引发父类中有同名成员出现,需要加作用域区分
#include <iostream>
using namespace std;
class Base1 {
public:
Base1()
{
m_A = 100;
}
public:
int m_A;
};
class Base2 {
public:
Base2()
{
m_A = 200;
}
public:
int m_A;
};
class Son : public Base2, public Base1
{
public:
Son()
{
m_C = 300;
m_D = 400;
}
public:
int m_C;
int m_D;
};
void test01()
{
Son s;
cout << "sizeof Son = " << sizeof(s) << endl;
cout << s.Base1::m_A << endl;
cout << s.Base2::m_A << endl;
}
int main() {
test01();
return 0;
}
5.8 菱形继承
两个派生类继承同一个基类; 又有两个类同时继承这两个派生类;
#include <iostream>
using namespace std;
class Animal
{
public:
int m_Age;
};
class Sheep : virtual public Animal {};
class Tuo : virtual public Animal {};
class SheepTuo : public Sheep, public Tuo {};
void test01()
{
SheepTuo st;
st.Sheep::m_Age = 10;
st.Tuo::m_Age = 20;
cout << "st.Sheep::m_Age = " << st.Sheep::m_Age << endl;
cout << "st.Tuo::m_Age = " << st.Tuo::m_Age << endl;
cout << "st.m_Age = " << st.m_Age << endl;
}
int main() {
test01();
return 0;
}
六、多态
6.1 多态的基本概念
多态分为两类: (1)静态多态: 函数重载 和 运算符重载属于静态多态,复用函数名; (2)动态多态: 派生类和虚函数实现运行时多态。 静态多态和动态多态的区别: (1)静态多态的函数地址早绑定 - 编译阶段确定函数地址 (2)动态多态的函数地址晚绑定 - 运行阶段确定函数地址
#include <iostream>
using namespace std;
class Animal
{
public:
virtual void speak()
{
cout << "动物在说话" << endl;
}
};
class Cat :public Animal
{
public:
void speak()
{
cout << "小猫在说话" << endl;
}
};
class Dog :public Animal
{
public:
void speak()
{
cout << "小狗在说话" << endl;
}
};
void DoSpeak(Animal & animal)
{
animal.speak();
}
void test01()
{
Cat cat;
DoSpeak(cat);
Dog dog;
DoSpeak(dog);
}
int main()
{
test01();
return 0;
}
6.2 纯虚函数和抽象类
在多态中,通常父类中虚函数的实现是毫无意义的,主要都是调用子类重写的内容,因此可以将虚函数改为纯虚函数。
纯虚函数语法:virtual 返回值类型 函数名 (参数列表)= 0 ; 当类中有了纯虚函数,这个类也称为抽象类。
抽象类特点: (1)无法实例化对象; (2)子类必须重写抽象类中的纯虚函数,否则也属于抽象类。
#include <iostream>
using namespace std;
class Base
{
public:
virtual void func() = 0;
};
class Son :public Base
{
public:
virtual void func()
{
cout << "func函数调用" << endl;
};
};
void test01()
{
Base *base = new Son;
base->func();
}
int main()
{
test01();
return 0;
}
6.3 虚析构和纯虚析构
多态使用时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码。
解决方式:将父类中的析构函数改为虚析构或者纯虚析构。
虚析构和纯虚析构共性: (1)可以解决父类指针释放子类对象; (2)都需要有具体的函数实现。
虚析构和纯虚析构区别: 如果是纯虚析构,该类属于抽象类,无法实例化对象。
虚析构语法: virtual ~类名(){}
纯虚析构语法: virtual ~类名() = 0; 类名::~类名(){}
#include <iostream>
using namespace std;
#include <string>
class Animal
{
public:
Animal()
{
cout << "Animal 构造函数调用!" << endl;
}
virtual void Speak() = 0;
virtual ~Animal() = 0;
};
Animal::~Animal()
{
cout << "Animal 纯虚析构函数调用!" << endl;
}
class Cat : public Animal {
public:
Cat(string name)
{
cout << "Cat构造函数调用!" << endl;
m_Name = new string(name);
}
virtual void Speak()
{
cout << *m_Name << "小猫在说话!" << endl;
}
~Cat()
{
cout << "Cat析构函数调用!" << endl;
if (this->m_Name != NULL) {
delete m_Name;
m_Name = NULL;
}
}
public:
string *m_Name;
};
void test01()
{
Animal *animal = new Cat("Tom");
animal->Speak();
delete animal;
}
int main()
{
test01();
return 0;
}
|