C++ class 使用后的声明
C++ class declaration after using it
我想创建一个带有参数的方法,该参数链接到稍后声明的 Enemy
。
这是我的代码:
#include <iostream>
#include <vector>
using namespace std;
class Weapon{
public:
int atk_points;
string name;
string description;
void Attack(Entity target){
};
};
class Armor{
public:
int hp_points;
string name;
string description;
int block_chance;
};
class Entity{
public:
int hp;
int atk;
string name;
vector<Weapon> weapons;
vector<Armor> armors;
};
我试图搜索答案,但没有找到任何有用的信息。
这是错误日志:
prog.cpp:9:15: error: ‘Entity’ has not been declared
void Attack(Entity target){
你不能。
你必须早点申报。但是,在某些情况下,您可以稍后定义它。
要转发声明一个 class,请在使用前写下:
class Entity;
问题是编译器不知道Entity
在你用作参数类型的地方是什么。所以你需要告诉编译器 Entity
是一个 class 类型。
有两种方法可以解决这个问题,下面给出了两种方法:
方法一
要解决这个问题,您需要做以下两件事:
- 为 class
Entity
提供前向声明。
- 将
Attack
的参数设为引用类型,这样我们就可以避免不必要的参数复制,而且因为我们提供的是成员函数的定义,而不仅仅是声明。
class Entity; //this is the forward declaration
class Weapon{
public:
int atk_points;
string name;
string description;
//------------------------------v------------>target is now an lvalue reference
void Attack(const Entity& target){
};
};
方法二
解决这个问题的另一种方法是,您可以只在 class 中提供成员函数 Attack
' 的声明,然后在 class [=12] 之后提供定义=]的定义如下图:
class Entity; //forward declaration
class Weapon{
public:
int atk_points;
string name;
string description;
//------------------------------v----------->this time using reference is optional
void Attack(const Entity& target); //this is a declaration
};
//other code here as before
class Entity{
public:
int hp;
int atk;
string name;
vector<Weapon> weapons;
vector<Armor> armors;
};
//implementation after Entity's definition
void Weapon::Attack(const Entity& target)
{
}
在c++中,这样的代码无法编译:
class A {
void fooa(B) {}
};
class B {
void foob(A) {}
};
但是这样的代码是可以编译的,我们可以这样改代码:
class A { };
class B { };
void fooa(A *, B) {}
void foob(B *, A) {}
它有效,没有任何东西是递归的。
所以,我认为更改为引用不是一个好主意。直接的方法就是使用一些技巧。例如,将 Entity
更改为 auto
。就像那样:void Attack(auto target)
。
更重要的是,用c++20,你可以定义一个概念attackable,让Entity is attackable,我很喜欢。
我想创建一个带有参数的方法,该参数链接到稍后声明的 Enemy
。
这是我的代码:
#include <iostream>
#include <vector>
using namespace std;
class Weapon{
public:
int atk_points;
string name;
string description;
void Attack(Entity target){
};
};
class Armor{
public:
int hp_points;
string name;
string description;
int block_chance;
};
class Entity{
public:
int hp;
int atk;
string name;
vector<Weapon> weapons;
vector<Armor> armors;
};
我试图搜索答案,但没有找到任何有用的信息。 这是错误日志:
prog.cpp:9:15: error: ‘Entity’ has not been declared
void Attack(Entity target){
你不能。
你必须早点申报。但是,在某些情况下,您可以稍后定义它。
要转发声明一个 class,请在使用前写下:
class Entity;
问题是编译器不知道Entity
在你用作参数类型的地方是什么。所以你需要告诉编译器 Entity
是一个 class 类型。
有两种方法可以解决这个问题,下面给出了两种方法:
方法一
要解决这个问题,您需要做以下两件事:
- 为 class
Entity
提供前向声明。 - 将
Attack
的参数设为引用类型,这样我们就可以避免不必要的参数复制,而且因为我们提供的是成员函数的定义,而不仅仅是声明。
class Entity; //this is the forward declaration
class Weapon{
public:
int atk_points;
string name;
string description;
//------------------------------v------------>target is now an lvalue reference
void Attack(const Entity& target){
};
};
方法二
解决这个问题的另一种方法是,您可以只在 class 中提供成员函数 Attack
' 的声明,然后在 class [=12] 之后提供定义=]的定义如下图:
class Entity; //forward declaration
class Weapon{
public:
int atk_points;
string name;
string description;
//------------------------------v----------->this time using reference is optional
void Attack(const Entity& target); //this is a declaration
};
//other code here as before
class Entity{
public:
int hp;
int atk;
string name;
vector<Weapon> weapons;
vector<Armor> armors;
};
//implementation after Entity's definition
void Weapon::Attack(const Entity& target)
{
}
在c++中,这样的代码无法编译:
class A {
void fooa(B) {}
};
class B {
void foob(A) {}
};
但是这样的代码是可以编译的,我们可以这样改代码:
class A { };
class B { };
void fooa(A *, B) {}
void foob(B *, A) {}
它有效,没有任何东西是递归的。
所以,我认为更改为引用不是一个好主意。直接的方法就是使用一些技巧。例如,将 Entity
更改为 auto
。就像那样:void Attack(auto target)
。
更重要的是,用c++20,你可以定义一个概念attackable,让Entity is attackable,我很喜欢。