#include
using namespace std;
// 封装一个完整的Rect类
class Rect
{
private:
int m_nLength;
int m_nWidth;
public:
Rect(); // 无参构造函数
Rect(int mLength, int mWidth); // 两个int类型的构造函数
Rect(int mLength); // 一个int类型的构造函数
// 利用一组get和set方法来实现长度和宽度的设置、获取
// 设置长度和宽度
void setLength(int length);
void setWidth(int width);
// 获取长度和宽度
int getLength();
int getWidth();
// 定义方法来获取面积
int getArea();
};
// 在类外定义函数
// 定义构造函数
Rect::Rect(int mLength, int mWidth) :m_nLength(mLength), m_nWidth(mWidth) {}
Rect::Rect(int mLength) :m_nLength(mLength), m_nWidth(mLength) {}
void Rect::setLength(int length)
{
m_nLength = length;
}
void Rect::setWidth(int width)
{
m_nWidth = width;
}
int Rect::getLength()
{
return m_nLength;
}
int Rect::getWidth()
{
return m_nWidth;
}
int Rect::getArea()
{
return m_nWidth * m_nLength;
}
int main()
{
Rect r1(100, 50);
cout << "r1矩形的长是:" << r1.getLength() << ",矩形的宽是:" << r1.getWidth() << endl;
cout << "r1矩形的面积是:" << r1.getArea() << endl;
// 修改r1对象的长和宽
r1.setLength(300);
r1.setWidth(100);
cout << "修改长和宽之后的结果是:" << endl;
cout << "r1矩形的长是:" << r1.getLength() << ",矩形的宽是:" << r1.getWidth() << endl;
cout << "r1矩形的面积是:" << r1.getArea() << endl;
return 0;
}
示例
父类头文件及其cpp
#ifndef ANIMAL_H//在C/C++预处理指令中主要用于防止头文件被重复引用,避免重复编译。
#define ANIMAL_H
#include
using namespace std;
class Animal
{
private:
char m_cName[20]; // 姓名
int m_nAge; // 年龄
public:
// 构造函数
Animal(const char* name, int age);
~Animal();
// 获取名字
char* getName();
// 声明跑和叫的方法
void running();
void barking();
};
#endif // !ANIMAL_H
#include "Animal.h"//注意:不能忘记引入头文件
Animal::Animal(const char* name, int age)
{
strcpy_s(m_cName, name);
m_nAge = age;
cout << "Animal的构造函数" << endl;
}
Animal::~Animal()
{
cout << "Animal正在析构" << endl;
}
char* Animal::getName()
{
return m_cName;
}
void Animal::running()
{
cout << "姓名:" << m_cName << "正在跑" << endl;
}
void Animal::barking()
{
cout << "姓名:" << m_cName << "正在叫" << endl;
}
子类头文件及其cpp
#ifndef CAT_H
#define CAT_H
#include "Animal.h"//派生类继承父类,要引入父类头文件
class Cat:public Animal//public代表继承方式,表示公有继承
{
public:
Cat(const char* name, int nAge);
};
#endif // !CAT_H
#include "Cat.h"//由于头文件已经引入过父类头文件,这里直接引入子类自己的头文件
// 这里是先执行Animal的构造函数,简单理解就是要先有Animal再有Cat,因为Cat要从Animal继承
//成员
Cat::Cat(const char* name, int nAge) :Animal(name, nAge)
{
}
#ifndef DOG_H
#define DOD_H
#include "Animal.h"
//class Dog :public Animal
// 保护继承父类
//class Dog :protected Animal
// 私有继承
class Dog :private Animal
{
private:
// 子类新增成员,表示狗的类型
char m_cType[20];
public:
Dog(const char* name, int nAge, const char *nType);
~Dog();
//定义狗类自己的方法
void lookingHouse();
//void barking();
};
#endif // !DOG_H
#include "Dog.h"
Dog::Dog(const char* name, int nAge, const char* nType) :Animal(name,nAge)
{
// 将狗的类型赋值给私有成员m_cType
strcpy_s(m_cType, nType);
cout << "Dog的构造函数" << endl;
}
Dog::~Dog()
{
cout << "Dog正在析构" << endl;
}
//定义狗类自己的方法
void Dog::lookingHouse()
{
cout << "姓名:" << getName() << "正在看家" << endl;
barking();
}
#include "Dog.h"
int main()
{
Dog d("旺财", 18, "中华田园犬");
d.running();
d.barking();
d.lookingHouse();
}
//注:这些是放在不同文件下的,这里整理在了一块
#include "Dog.h"
Dog::Dog(const char* name, int nAge, const char* nType) :Animal(name,nAge)
{
// 将狗的类型赋值给私有成员m_cType
strcpy_s(m_cType, nType);
cout << "Dog的构造函数" << endl;
}
Dog::~Dog()
{
cout << "Dog正在析构" << endl;
}
//定义狗类自己的方法
void Dog::lookingHouse()
{
cout << "姓名:" << getName() << "正在看家" << endl;
barking();
}
// 重定义父类的方法,或者是子类同名方法将父类的方法给覆盖掉
void Dog::barking()
{
cout << "姓名:" << getName() << "正在叫,它的类型是:" << m_cType << endl;
}
#include "Dog.h"
int main()
{
Dog d("旺财", 18, "中华田园犬");
d.running();
d.barking();
d.lookingHouse();
}
#include
using namespace std;
// 基类A
class BaseA
{
protected:
int m_a;
int m_b;
public:
BaseA(int a, int b);
~BaseA();
};
BaseA::BaseA(int a, int b) :m_a(a), m_b(b)
{
cout << "A类正在构造" << endl;
}
BaseA::~BaseA()
{
cout << "A类正在析构" << endl;
}
// 基类B
class BaseB
{
protected:
int m_c;
int m_d;
public:
BaseB(int c, int d);
~BaseB();
};
BaseB::BaseB(int c, int d) :m_c(c), m_d(d)
{
cout << "B类正在构造" << endl;
}
BaseB::~BaseB()
{
cout << "B类正在析构" << endl;
}
// 定义类C来同时继承类A和类B
class C :public BaseA, public BaseB
{
private:
int m_e;
public:
C(int a, int b, int c, int d, int e);
~C();
void show();
};
C::C(int a, int b, int c, int d, int e) :BaseA(a, b), BaseB(c, d), m_e(e) {
cout << "C类正在构造" << endl;
}
C::~C()
{
cout << "C类正在析构" << endl;
}
void C::show()
{
cout << m_a << "\t" << m_b << "\t" << m_c << "\t" << m_d << "\t" << m_e << endl;
}
int main()
{
C c1(10, 20, 30, 40, 50);
c1.show();
return 0;
}
/*
运行结果:
A类正在构造
B类正在构造
C类正在构造
10 20 30 40 50
C类正在析构
B类正在析构
A类正在析构
*/
#include
using namespace std;
// 动态多态实现同一个方法的不同实现结果
class Person
{
public:
void buyTicket();
};
void Person::buyTicket()
{
cout << "普通人买全票" << endl;
}
class Student :public Person
{
public:
void buyTicket()
{
cout << "学生买半票" << endl;
}
};
class Child :public Person
{
public:
void buyTicket()
{
cout << "儿童免票" << endl;
}
};
int main()
{
Person* p[3];
Person p1;
Student s1;
Child c1;
// 用父类指针指向子类对象
p[0] = &p1;
p[1] = &s1;
p[2] = &c1;
p[0]->buyTicket();
p[1]->buyTicket();
p[2]->buyTicket();
return 0;
}
#include
using namespace std;
// 动态多态实现同一个方法的不同实现结果
class Person
{
public:
// 声明函数是虚函数的时候,只需要在函数类型之前加virtual关键字即可
virtual void buyTicket();
};
// 只在类内声明的时候才写virtual关键字,类外定义的时候不需要写
void Person::buyTicket()
{
cout << "普通人买全票" << endl;
}
class Student :public Person
{
public:
// 子类中的virtual可写可不写,一般建议写
virtual void buyTicket()
{
cout << "学生买半票" << endl;
}
};
class Child :public Person
{
public:
// 子类中的virtual可写可不写,一般建议写
void buyTicket()
{
cout << "儿童免票" << endl;
}
};
int main()
{
// 静态多态能不能用父类的指针指向子类的方法呢?
Person* p[3];
Person p1;
Student s1;
Child c1;
// 用父类指针指向子类对象
p[0] = &p1;
p[1] = &s1;
p[2] = &c1;
p[0]->buyTicket();
p[1]->buyTicket();
p[2]->buyTicket();
return 0;
}
#include
using namespace std;
// 定义父类 Employee
class Employee
{
private:
char* name;
int age;
public:
Employee(const char* n, int a);
virtual ~Employee();
};
Employee::Employee(const char* n, int a)
{
// 动态开辟空间,将地址给到name指针变量上
name = new char[strlen(n) + 1];
strcpy_s(name, strlen(n) + 1, n);
age = a;
cout << "正在构造" << name << endl;
}
Employee::~Employee()
{
cout << "正在释放:" << name << endl;
// 如果name不为空就将name中的空间释放掉
if (name)
{
delete[] name;
name = NULL;
}
}
// 定义子类Teacher
class Teacher :public Employee
{
private:
char* project; // 定义成员来存储科目
public:
Teacher(const char* n, const char* pro, int a);
~Teacher();
};
Teacher::Teacher(const char* n, const char* pro, int a) :Employee(n, a)
{
project = new char[strlen(pro) + 1]; // 动态申请空间,给到指针project上
strcpy_s(project, strlen(pro) + 1, pro);
cout << "正在构造教师类" << endl;
}
Teacher::~Teacher()
{
cout << "正在释放教师类,课程是:" << project << endl;
if (project)
{
delete[] project;
project = NULL;
}
}
int main()
{
// 析构函数不是虚函数,释放内存的时候,只调用基类的析构函数,子类数据成员占用的空间没有被释放
// 当父类的析构函数定义为虚析构函数,子类的析构会自动转变为虚析构函数,在释放父类的同时也会将子类给释放掉
Employee* p[3];
// 直接创建对象,会自动调用析构函数,因为对象有自己的生命周期,在它调用结束的时候会自动执行析构函数
// Employee p1("dijia", 1000);
p[0] = new Employee("zhangsan", 20);
p[1] = new Teacher("lisi", "C++", 18);
p[2] = new Teacher("wangwu", "python", 28);
for (int i = 0; i < 3; i++)
{
delete p[i];
}
return 0;
}
#include
using namespace std;
class Person
{
public:
// 声明纯虚函数
virtual void say() = 0;
};
class Student:public Person
{
public:
void say()
{
cout << "学生say hi" << endl;
}
};
class Child :public Person
{
};
int main()
{
Student s1;
s1.say();
// 如果继承了父类的纯虚函数,并且没有重写,那么子类也是抽象类,不能实例化对象
// Child c1;
// 父类有纯虚函数,所以是抽象类,不能实例化
// Person p;
return 0;
}
#include
using namespace std;
class A
{
private:
char* str;
public:
A(const char* s = "no data");
~A();
// 重载赋值运算符
A& operator=(const A& a);
void print();
};
A::A(const char* s)
{
str = new char[strlen(s) + 1];
strcpy_s(str, strlen(s) + 1, s);
}
A& A::operator=(const A& a)
{
if (str)
{
delete[] str;
}
// 每次赋值str都会新开辟一段空间,避免赋值的时候多个str使用同一个地址
str = new char[strlen(a.str) + 1];
strcpy_s(str, strlen(a.str) + 1, a.str);
return *this;
}
A::~A()
{
if (str != NULL)
{
delete[] str;
str = NULL;
}
}
void A::print()
{
cout << str << endl;
}
int main()
{
// 在主函数中定义class A的对象,将地址赋值给p,再利用默认的赋值运算符将p给到a1
// 第一次调用print() 可以正常输出,但是删除p所指向对象时,就会调用析构函数
// 将str所指向的内存空间给释放掉,再次调用print()方法的时候就会报错
A* p = new A("A String");
A a1, a2;
a1 = a2 = *p;
a1.print();
delete p; // 如果使用了重载赋值,三个str的地址就都不相同了,如果释放了p指向的地址,并不会影响a1 和 a2的空间,所以仍然可以输出
a1.print();
a2.print();
return 0;
}