C++在父母子女回报功能
说实话,我真的不知道,怎么问这个问题,所以请别生气:)C++在父母子女回报功能
无论如何,我希望有存取器(setter方法)在我的课返回this
允许的jQuery样a.name("something").address("somethingelse");
我有一个父类(Entity
)和几个childclasses(Client, Agent etc.
)。对于大多数事情来说,mutators是从Entity
类(如名称或地址)继承而来的,但它们返回一个Entity
对象,所以我无法在它们上调用Client增强器。
换句话说:
// name mutator
Entity& Entity::name(const string& name) {
// [...] checks
_name = name;
return *this;
}
// budgetRange mutator
Client& Client::budgetRange(const long int& range) {
// [...] checks
_budgetRange = range;
return *this;
}
然后当我把它称为:
Client a; a.name("Dorota Adamczyk").budgetRange(50);
编译器(逻辑)说,该实体对象没有budgetRange成员(因为名字返回一个实体,不是客户)。
我现在的问题是:如何可以实现这样的事情?我想到了在childclasses超载所有的实体功能,但是这不会是好的,是对继承:)
预先感谢您为您的想法的想法:d
您应该使用CRTP。
template<class Derived>
class Entity
{
Derived* This() { return static_cast<Derived*>(this); }
public:
Derived& name(const string& name)
{
...
return *This();
}
};
class Client : public Entity<Client>
{
public:
Client& budgetRange(const long& range)
{
...
return *this;
}
};
如果你想使用虚拟功能,你还可以添加抽象基类,像这样:
class AbstractEntity
{
public:
virtual void foo() = 0;
virtual ~AbstractEntity();
};
template<class Derived>
class Entity : AbstractEntity
{...};
的“好奇递归模板“模式可以在这里帮助;使基类的模板,通过派生类parametrised,沿着线:
template <typename Derived>
struct Entity {
Derived & name(std::string const & name) {
// stuff
return static_cast<Derived&>(*this);
}
};
struct Client : Entity<Client> {
Client & budget(long range) {
// stuff
return *this;
}
};
Client().name("Mike").budget(50); // should compile
如果所有类型直接从Entity
继承这只会工作。如果你需要类型是多态的(即所有类型都共享一个基类),那么你需要添加另一个非模板基类,并且从中继承。
非常感谢您的回答,但是我会选择Abyx'one,因为他包含了这个()的想法:) Upvoted。 – Asmodiel 2011-12-20 13:25:08
现在,几乎所有已经说过,我要加一块答案允许一个人在继承的多层次使用CRTP:
当一个人想从Client
继承,因为Derived
将把Client
以上CRTP实现突破。如果你希望能够使用CRTP模式进行了继承的多层次的命名参数成语,你需要像这样
template<class Derived>
class Entity_T
{
protected:
Derived* This() { return static_cast<Derived*>(this); }
public:
Derived& name(const string& name)
{
...
return *This();
}
};
template<class Derived>
class Client_T : public Entity_T<Derived>
{
Derived& budgetRange(const long& range)
{
...
return *This();
}
};
编写你的类提供给用户的Client_T
一个免费的模板版本添加
class Client : public Client_T<Client> {};
这是否值得扩大的代码库完全取决于你。请注意,我没有编译上面的代码。也为`方法chaining`和`命名参数idiom`,
谷歌这是你在做什么。请注意,从'Client'继承时,您的代码将在下面使用CRTP解决方案再次中断。 – cheind 2011-12-20 13:40:05