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{/*…*/}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");