构造函数
#include <iostream>
#define LOG(x) std::cout << x << std::endl
using namespace std;
class Entity {
public:
float X, Y;
Entity(){ //构造函数 在函数执行时默认自动执行 省去main 的代码长度
X = 0.0f;
Y = 0.0f;
}
Entity(float x, float y){ //构造函数带参数 可以在main 中调用
X = x;
Y = y;
}
void Print(){
LOG("X: " << X << " Y: " << Y);
}
};
int main(){
Entity e1{1.0f, 2.0f};
e1.Print();
cin.get();
}
解析函数
简介::解析函数就是在创造函数时进行销毁对象避免内存运行溢出
#include <iostream>
#define LOG(x) std::cout << x << std::endl
using namespace std;
class Entity {
public:
float X, Y;
Entity(){ //构造函数 在函数执行时默认自动执行 省去main 的代码长度
LOG("对象已创建");
X = 0.0f;
Y = 0.0f;
}
Entity(float x, float y){ //构造函数带参数 可以在main 中调用
X = x;
Y = y;
}
~Entity(){ //析构函数 自动调用 释放内存
LOG("对象已销毁");
}
void Print(){
LOG("X: " << X << " Y: " << Y);
}
};
void Function(){ //函数
Entity e1;
e1.Print();
e1.~Entity(); //调用析构函数 释放内存
}
int main(){
Function();
cin.get();
}
虚函数
虚函数允许我们在子类重写方法功能
#include <iostream>
#include <string>
class Entity { // 实体类
public:
std::string GetName(){ // 获取名称
return "Entity";
}
};
class Player : public Entity { // 玩家类,继承自实体类
private:
std::string m_Name; // 名称
public:
Player(const std::string& name) : m_Name(name){} // 构造函数
std::string GetName(){ // 获取名称
return m_Name;
}
};
// 打印名称
//这里我们打印的是Entity的GetName()方法,而不是Player的GetName()方法
void PrintName(Entity* entity) { // 打印名称
std::cout << entity->GetName() << std::endl;
}
int main() {
Entity* e = new Entity(); // 创建实体对象
PrintName(e); // 打印名称
Player* p = new Player("Player"); // 我这里系统打印一个新的对象
//但是打印 了俩词Entity,因为Player继承自Entity,所以打印的是Entity的GetName()
//原因是我们通常声明函数时 我们的方法通常只在函数内部起作用 当调用方法时 就会调用属于该类型的对象方法
//需要写一个虚汗数覆盖掉GetName()方法
PrintName(p); // 打印名称
std::cin.get();
}
加了虚函数之后
virtual 虚函数
#include <iostream>
#include <string>
class Entity { // 实体类
public:
//virtual 虚函数
virtual std::string GetName(){ // 获取名称
return "Entity";
}
};
class Player : public Entity { // 玩家类,继承自实体类
private:
std::string m_Name; // 名称
public:
Player(const std::string& name) : m_Name(name){} // 构造函数
//防复写函数
std::string GetName() override { // 获取名称
return m_Name;
}
};
// 打印名称
//这里我们打印的是Entity的GetName()方法,而不是Player的GetName()方法
void PrintName(Entity* entity) { // 打印名称
std::cout << entity->GetName() << std::endl;
}
int main() {
Entity* e = new Entity(); // 创建实体对象
PrintName(e); // 打印名称
Player* p = new Player("Player"); // 我这里系统打印一个新的对象
//但是打印 了俩词Entity,因为Player继承自Entity,所以打印的是Entity的GetName()
//原因是我们通常声明函数时 我们的方法通常只在函数内部起作用 当调用方法时 就会调用属于该类型的对象方法
//需要写一个虚汗数覆盖掉GetName()方法
PrintName(p); // 打印名称
std::cin.get();
}
C++ 虚函数
纯虚函数确保了每一个类都有一种特定的方法
这个类可以是 抽象的基类 作为参数类型放入一个通用函数里
然后调用做其他事情
#include <iostream>
#include <string>
//在c++中 接口只是c++的类 其他语言interface 都可以理解为接口
class Printable {
public:
virtual std::string GetClassName() = 0; // 纯虚函数,返回名称数
};
//实体类
class Entity : public Printable { // 继承接口类
public:
virtual std::string GetName() {return "Entity";} // 虚函数,返回名称(回调函数)
std::string GetClassName() {return "Entity";} // 提供纯回调函数功能使其实体类具备接口类功能
};
// 玩家类 继承实体类和接口类
class Player : public Entity //这里Player类继承了Entity和Printable接口类 所义Player类实现了Printable接口的GetName()方法
{
private:
std::string m_Name; // 名称
public:
Player(const std::string& name) : m_Name(name){} // 构造函数
std::string GetName() {return m_Name;}
std::string GetClassName() override {return "Player";} //在这里需要定义纯虚函数GetClassName() 使其具备接口类功能
/*虚函数在这里就用上了,因为Player类继承了接口类Printable,而接口类Printable中有虚函数GetClassName(),所以Player类也必须实现该虚函数,否则无法调用接口类中的纯虚函数
* 虚函数不像函数一样可以直接调用,而是需要通过指针或引用调用,所以这里Player类通过接口类指针或引用调用纯虚函数GetClassName()
* 虚函数可以进行复写,即子类可以重新定义父类的虚函数,这样就可以实现多态,即不同子类可以有不同的功能*/
};
// 打印名称
//这里我们打印的是Entity的GetName()方法,而不是Player的GetName()方法
void PrintName(Entity* entity) { // 打印名称
std::cout << entity->GetName() << std::endl;
}
//
void Print(Printable* obj){
std::cout << obj->GetClassName() << std::endl;
}
//虚函数的引用和使用
class A : public Printable {
public:
std::string GetClassName() override { return "A"; }
};
int main() {
Entity* e = new Entity(); //使用irtual std::string GetName() = 0;
/* 虚函数
导致无法调用GetName()方法,因为接口类没有实现GetName()方法,所以这里会报错
如过想要调用接口类的方法,则需要使用接口类指针或引用,而不是实体类指针或引用
或者提供一个函数实体的功能*/
Player* p = new Player("cherno");
Print(e);
Print(p);
Print(new A()); //打印A的类名
std::cin.get();
}