我只是想着它,想知道它是否完全可能,只是出于好奇,因为我认为它非常有用。 (但我的大多数想法都是疯狂/疯狂的。)
所以这就是:
是否可以创建A类和B类,然后使用B类将成员添加到A类中?
让我们假设我们正在制作一个游戏,或者一些有用的程序:
class Player
{
public:
float health;
};
现在,您想到了一种通过使用包含文件或其他内容来允许扩展的方法:
#define INCLUDE_SPEEDO_METER
#ifdef INCLUDE_SPEEDO_METER
class PlayerSpeedo : public Player
{
public:
float absolute_speed;
//Do some Magic here & there
};
#endif
现在让我们假设我们想要Player
类Player.absolute_speed
类来访问玩家的绝对速度。
这有可能吗?
答案 0 :(得分:2)
不,那是不可能的。你不能“注入”成员到另一个类。坦率地说,我不明白为什么你会想要。除了你之外没有人会意识到这个“注射”的成员。
答案 1 :(得分:1)
你所谈论的内容在静态类型语言中是不可能的,但它可以使用动态类型语言(如Python)。
在C ++中实现这一目标的一种方法是在属性的字符串名称和属性值的一些通用包装器之间使用Map。
答案 2 :(得分:1)
虽然你无法在语法上做你希望做的事情,但你可以通过在基类中存储map
来实现非常接近的目标。
class Player
{
public:
Player(float health = 0) { data["health"] = health; }
float health() const { return get("health"); }
float get(std::string const& field) const { return data[field]; }
protected:
std::map<std::string, float> data;
};
class PlayerSpeedo : public Player
{
public:
PlayerSpeedo(float absolute_speed) {data["absolute_speed" = absolute_speed; }
float absolute_speed() const { return get("absolute_speed"); }
};
答案 3 :(得分:1)
不是你所要求的,但是最近有关C ++标准未来版本的提案Call syntax: x.f(y) vs. f(x,y)
会给你一些类似的功能这将使您能够编写一个独立的函数float absolute_speed(const Player& p) { return 0.0f; }
,您可以通过Player p; auto speed = p.absolute_speed()
调用该函数,而无需更改Player的定义。这与C#中的扩展方法类似。
答案 4 :(得分:1)
也许你喜欢通过另一个类使用如下模板扩展基类的方法。不需要运行时多态性,这通常是速度的标准,而优化可以归结为执行的函数而不会停止虚函数。
从示例中可以看出,它看起来像注入方法和属性。 C ++ 11使它可以使用类中的构造函数来扩展给定的类,非常简单。好的,这是一个愚蠢的例子,但也许它会让你知道这件事是如何运作的。
#include <iostream>
class Empty
{
public:
void DoSomething() { std::cout << "Nothing" << std::endl;}
};
class Extender
{
private:
int x;
public:
Extender(int _x):x(_x) {}
void DoSomething() { std::cout << "Value " << x << std::endl; }
};
template <typename ExtendWith>
class User: public ExtendWith
{
public:
using ExtendWith::ExtendWith;
void DoIt() { ExtendWith::DoSomething(); }
};
int main()
{
User<Empty> userEmpty;
userEmpty.DoIt();
User<Extender> userExtended(100);
userExtended.DoIt();
}
答案 5 :(得分:0)
我不认为这种语言可以在不引入不一致的情况下允许您尝试做的事情。
我认为您不想修改实际类型,因为您所描述的实际上是将超类型实例转换为子类型实例。你可以通过向子类型添加构造函数来实现这一点......
class PlayerSpeedo : public Player {
public:
float absolute_speed;
explcit PlayerSpeedo(const Player& p, float absolute_speed=0, ...) : health(p.health) {
// copy Player values
}
另一个选项可能是存储对原始对象的引用,decorating它。但这并没有改变类型。