C++ 返回派生类类型的基类中的方法?
我有一堆类,它们有一个共同的函数,只是它返回一个指向它们自己类型的指针。代码看起来是一样的,我想把它移到一个抽象基类中。但是我如何使从中继承的类返回它们自己的类型呢C++ 返回派生类类型的基类中的方法?,c++,inheritance,c++11,return-type,generic-programming,C++,Inheritance,C++11,Return Type,Generic Programming,我有一堆类,它们有一个共同的函数,只是它返回一个指向它们自己类型的指针。代码看起来是一样的,我想把它移到一个抽象基类中。但是我如何使从中继承的类返回它们自己的类型呢 class base { base *foo() { // ... } }; class derived : public base { }; derived d; d.foo(); // Should return derived* instead of base* P> > C++ >
class base {
base *foo() {
// ...
}
};
class derived : public base {
};
derived d;
d.foo(); // Should return derived* instead of base*
<> P> > C++ >支持,这是C++中的一种方式。这叫做协变返回类型。您只需声明虚函数并相应地声明返回类型。就这些
struct base {
virtual base *foo() {
// ...
}
};
struct derived : public base {
virtual derived *foo() {
// ...
}
};
derived d;
base *base_ptr = d.foo();
现在,你的一条评论扩展了原来的问题: 但实际上我的目标是不重复功能体,因为它是 除了使用的类型外,其他类型相同 这是不可能的 有各种各样的技术可以促进重复,但是你不能回避这样一个事实:无论你做什么,你仍然必须自己创建函数体 一种这样的技术是使用宏,代价是混淆和宏带来的所有其他缺点;但是,宏不会自动出现在类中。你必须把它放在那里
// beware of macros!
#define FOO(T) virtual T *foo() { return new T; }
struct base {
FOO(base)
virtual ~base() {} // let's not forget the virtual destructor
};
struct derived : public base {
FOO(derived)
};
类似的方法是使用模板促进功能体的重复:
template <class T>
T *ComplicatedFunctionReturningT()
{
T *t;
// ...
// ...
// ...
return t;
}
struct base {
virtual base *foo() {
return ComplicatedFunctionReturningT<base>();
}
virtual ~base() {} // let's not forget the virtual destructor
};
struct derived : public base {
virtual derived *foo() {
return ComplicatedFunctionReturningT<derived>();
}
};
当然,只有在函数体非常复杂的情况下,所有这些才是真正值得的。对于极端情况,完全不同的方法是<强>使用某些外部工具或脚本< /强>生成< C++代码> < /P>
最后,如果这真的是一个问题,请从整体上重新考虑您的设计。也许您并不真正需要该函数,或者您的程序试图解决的实际问题不需要OOP。根据您对答案的评论,您可以实现一个模板帮助器方法,以避免重复您将使用的代码:
class base
{
protected:
template<class T> T* fooInternal()
{
T* t = new T();
// do stuff with t
return t;
}
public:
virtual base* foo() { return fooInternal<base>(); }
};
class derived : public base
{
public:
virtual derived* foo() { return fooInternal<derived>(); }
};
类基
{
受保护的:
模板T*fooInternal()
{
T*T=新的T();
//用t做东西
返回t;
}
公众:
虚拟基*foo(){return foointeral();}
};
派生类:公共基
{
公众:
虚拟派生*foo(){return foointeral();}
};
一个选项是使用(奇怪的重复模板模式)
好吧,这是一个开始。但实际上,我的目标是不重复函数体,因为除了使用的类型之外,它是相同的。非常感谢你带我通过不同的选项!我喜欢模板方法,它引入了一些额外的复杂性,但仍然是最合适的。是的,我现在正在重新考虑我的设计。我还不满意,但我目前还没有一个更好的主意。”丹尼尔:实际上,在C++中,默认的应该是让虚拟成员函数私有而公共的非虚拟函数。公共虚拟函数应该是该规则的一个例外(当然,析构函数除外)。请看Herb Sutter的这篇老文章:实际上我不使用OOP意义上的类。这只是一种延迟共享代码和为我定义接口的方式。@danijar:按照OOP的通常定义,一个虚拟函数的存在使您的类成为一个OOP类。但那真是令人毛骨悚然。在软件工程的世界里,几乎没有一个词像“OOP”这样被过度使用和滥用了。还有一件事,我还有一个stl容器,比如
std::unordered_map
,应该作为std::unordered_map
继承到派生类中。有办法做到这一点吗?我考虑过类型特征,但不知道如何在这里应用它们。@danijar:不能重写成员变量;你必须在每节课上声明它。但是您可以使用与函数类似的技术。例如,对模板使用多重继承(公共+私有)<代码>模板结构ContainsMap{std::无序映射;};派生类:公共基,私有ContainsMap{/*…*/}因此,解决方案就是将所有通用代码放入基类,并将其模板化。听起来不错。@danijar:或多或少。危险总是过度设计。这项技术看起来很酷,可以很容易地吸引你进入问题解决方案搜索领域。如果您不确定它是否值得,请保持简单,并在每个类中重复声明。好的。当我想访问嵌套类型(如t::sub_type
)时,我似乎无论如何都无法应用此方法,因为必须首先知道依赖范围。然而,在上面发布的Jarod42文章中可能会出现这种情况。有趣的阅读:我认为做你想做的事情没有多大意义。为了使函数体相同,必须通过公共基类派生接口在函数体中引用返回的对象。这意味着另一个虚拟函数或该指针。在任何情况下,函数都返回一个实际的派生类对象。知道了这一点,一个可能的解决方案是使用一个helper函数简单地向下转换指针。这似乎是在尝试使用继承构建流畅接口时的一个常见问题。
class base
{
protected:
template<class T> T* fooInternal()
{
T* t = new T();
// do stuff with t
return t;
}
public:
virtual base* foo() { return fooInternal<base>(); }
};
class derived : public base
{
public:
virtual derived* foo() { return fooInternal<derived>(); }
};
template<typename Derived>
struct base {
Derived* foo() {
// ...
return static_cast<Derived*>(this);
}
};
struct derived : base<derived> {
// ...
};
derived d;
derived *derived_ptr = d.foo();
template<typename Derived>
struct base {
Derived* foo() {
// ...
return self();
}
private:
Derived* self() {
return static_cast<Derived*>(this);
}
};
SomePropertyObject()
.setBaseProperty("foo")
.setDerivedProperty("bar");