c++ - 基类返回指向派生类的指针,而无需在 C++ 中显式强制转换

标签 c++ pointers inheritance polymorphism

我感兴趣的是是否可以从基类中定义的方法返回指向派生类的指针,而无需将其显式强制转换为派生类。这个想法是接收者通过指向基类的指针接收到指向派生类的指针,并通过多态性将其视为派生类。

例如,可以这样做:

template<typename TClassType>
class A
{

public:
    virtual std::shared_ptr<TClassType const> execute(void)
        {
            return std::shared_ptr<TClassType const>
                (static_cast<TClassType*>(this));
        }
};

在这里,派生类作为模板参数传递。

但是,我想做的是类似这样的事情:

template<typename TBaseClassType>
class A
{

public:
    virtual std::shared_ptr<TBaseClassType const> execute(void)
        {
            return this;
        }
};

我想以这样一种方式来做,即返回的指向 base 的指针相对于原始派生类仍然是多态的。 TBaseClassType 可以是类 A,但也可以在类 A 和继承树中的派生类之间,即 A->TBaseClassType->派生Derived 是调用 execute() 的类。

注意1:必须是指向const的指针(也可以是指向const的const指针)。

注意 2:我理解为什么这个特定的解决方案不起作用,如果有人知道解决该问题的方法,而不是直接的方法,我很感兴趣。


编辑。我决定使用的解决方案总结在我对已接受答案的最后评论中。

最佳答案

首先,有协变的返回类型。这意味着例如一个clone()函数可以定义为返回 base*在基类中并返回一个 derived*在派生类中。不过这不是你的问题,因为这两种类型 shared_ptr<base>shared_ptr<derived>不是协变的,它们完全不相关。有很多方法可以解决这个问题,但它们需要一些工作:

class base
{
public:
    smart_ptr<base> clone() const
    { return smart_ptr<base>(this->do_clone()); }
private:
    virtual base* do_clone()
    { return new base(*this); }
};

如您所见,返回智能指针的公共(public)函数调用返回原始指针并且可以使用协变返回类型的私有(private)虚函数。现在派生类:

class derived: public base
{
public:
    smart_ptr<derived> clone() const
    { return smart_ptr<derived>(this->do_clone()); }
private:
    virtual derived* do_clone()
    { return new derived(*this); }
};

这个类几乎包含相似的代码,只是它派生自 base。 .现在,如果您有对派生类的引用(或指针/智能指针),调用 clone()在它上面会给你一个正确类型的指针。在对基类的引用上调用它会给你一个静态类型为 base 的指针。但是谁的动态类型仍然是正确的派生类。这是有效的,因为成员函数的查找在实现该函数的最派生类中停止,然后停止。所以基本上这是在基类中覆盖虚函数和隐藏函数的混合体。

注意事项:

  • 我故意写了“smart_ptr”,即使你写了 shared_ptr,因为对于这个特定的例子,使用 auto_ptr (C++98) 或 unique_ptr (C++11) 将是更好的选择,因为没有共享引用。
  • 实现clone()时, 我也会 assert() do_clone() 返回的指针是非空的,它指向与 this 相同的动态类型使用 typeid .如果该断言触发,有人忘记覆盖 do_clone()在派生类中。
  • 您不能在基类中返回派生类型,因为这需要一个依赖循环,而且根本不能确定基类对象是否也是派生对象。
  • 您可以创建一个模板函数,您将传递预期的类型,然后 dynamic_cast对于请求的类型,我会把这个决定留给你。语法将类似于 derived* derived_ptr = base_ptr->execute<derived>() ,我想。

关于c++ - 基类返回指向派生类的指针,而无需在 C++ 中显式强制转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27608909/

相关文章:

c++ - 如何在 visual studio 2010 中包含 DDK header ?

c - 用用户输入填充 *char[]

c - 带 header 的 RPN,为什么不起作用?

javascript - 在 "constructor"中设置 "prototype"属性的优点

c++ - 在没有任何关联指针或变量的情况下释放存储在堆栈中的整数

c++ - 使用 Struct 的动态 vector

c++ - 从中心而不是从左、中间旋转

c++ - 括号内和括号外的指针

c++ - 如何解决具有多个派生类的抽象基类的继承

.net-3.5 - 派生类型不能隐式转换为基接口(interface)