首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >继承自enable_shared_from_this返回shared_ptr of self的类的子类

继承自enable_shared_from_this返回shared_ptr of self的类的子类
EN

Stack Overflow用户
提问于 2015-12-09 21:53:01
回答 4查看 1.1K关注 0票数 5

我想知道是否存在这样的伪代码:

代码语言:javascript
运行
复制
class A : public std::enable_shared_from_this<A> {
    public:
        std::shared_ptr<self_t> getPtr(){
            return std::static_pointer_cast<self_t>(shared_from_this());
        }
};

class B : public A {
    std::vector<A> container;

    std::shared_ptr<self_t> addChild(A child){
        container.push_back(child);
        return getPtr();
    }
};

class C : public B {
    public:
        std::shared_ptr<self_t> doSomething(){
            // something
            return getPtr();
        }
};

int main(){
    A obja = new A();
    C obj = new C();
    obj->addChild(obja)->doSomething()
}

我的目标是一个对象代表一个视图(如MVC中的V),并且方法能够返回自己的链式调用。例:->setTop(0)->addChild(child1)->setBottom(0)

我已经读到,做一些像重载<<操作符这样的事情可能更容易,但我不认为这样做的效果很好,或者看起来很漂亮。

其中一个想法是创建一个名为VIEW(name,parent)的宏,该宏将使用模板进行扩展,但我对自我引用的默认模板参数有异议。

任何帮助都将不胜感激。

-编辑--

在坚果壳中,我希望从enable_shared_from_this继承一个基类。基类将有一个返回共享指针的方法,如doSomething。当派生类从基类继承时,我希望doSomething方法返回指向派生类的共享指针。我希望能够做到这一点,而不需要在派生类中重写doSomething

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2016-01-11 03:25:28

这种概念将被扩展方法所涵盖,这些方法存在于类定义之外,不违反类权限,但可以像方法一样调用.它存在于C#中,但目前不存在于C++中。C#中的代码如下所示:

代码语言:javascript
运行
复制
// c# syntax
namespace MyBaseExtensions {
    public static class MyBaseExt {
        public static shared_ptr<T> getPtr<T>(this T self) where T : MyBase 
        {
            return static_pointer_cast<T>(self.shared_from_this());
        }
    }
}

这允许操作符链接,因为类行MyBase的每个继承都有自己的函数定义,因为函数不是继承的方法,而是直接应用于每个相关类型。

反对的理由是,扩展会以通常不需要的功能污染对象,而独立的模板函数也会做同样的事情。问题是,按照这种逻辑:

代码语言:javascript
运行
复制
int main(){
    A obja = new A();
    C obj = new C();
    obj->getPtr()->addChild(obja)->doSomething()
}

最后看起来就像

代码语言:javascript
运行
复制
int main(){
    A obja = new A();
    C obj = new C();
    doSomething(addChild(getPtr(obj),obja)); //eyeroll.
}

您仍然需要声明模板函数,如

代码语言:javascript
运行
复制
// C++ syntax
namespace MyBaseExtensions {
    template<typename T> std::shared_ptr<T> getPtr<T>(T self)
    {
        return std::static_pointer_cast<T>(self->shared_from_this());
    }
}

至于将模板唯一地应用于每个派生类型的简单内部方法,我不确定有哪种。这样做的原因是,您想要的功能不是方法继承,而是每个未来的类都会自动继承它专门处理的模板(并且生成的方法不是继承就是隐藏)。为此,C++类需要具有非继承的专用公共方法,这些方法不在当前访问权限的公共、私有和受保护或模板功能的范围之内。

我会很高兴找到一个很好的方法来摆脱操作员链。

既然我浪费了你的时间,我就做了一个尝试:

代码语言:javascript
运行
复制
#include <vector>
#include <memory>

// 0 argument, creates an overload method (and hides parent class method)
//           from template method func_name
// template method specialization of a parent method does not work
//      so we use C++11 automatic type deduction to figure the      
//         template return type and return what the template returns
#define FUNC_DEF_0(base, cur, func_name) \
    auto func_name() \
            -> decltype(base().func_name<cur>()) { \
        return base::func_name<cur>(); \
    }

// 1 argument
#define FUNC_DEF_1(base, cur, func_name, arg1_t) \
    auto func_name(arg1_t param1) \
            -> decltype(base().func_name<cur>(param1)) { \
        return base::func_name<cur>(param1); \
    }

// class A
// add to class to hide class A methods
#define HIDE_A(current) \
    FUNC_DEF_0(A, current, getPtr)

class A : public std::enable_shared_from_this<A> {
public:
    template<typename _T = A>
    std::shared_ptr<_T> getPtr(){
        return std::static_pointer_cast<_T>(shared_from_this());
    }
};


// class B
// add to class to hide class B methods with new methods
#define HIDE_B(current) \
    HIDE_A(current) \
    FUNC_DEF_1(B, current, addChild, A)

class B : public A {
public:
    std::vector<A> container;

    template<typename _T = B>
    std::shared_ptr<_T> addChild(A child){
        container.push_back(child);
        return A::getPtr<_T>();
    }

    HIDE_A(B); // hide A methods with B specialized methods

    // Example method hiding
    // auto getPtr() -> decltype(A().getPtr<B>()) {
    //     return base::getPtr<B>();
    // }
};


// class C
// add to class to hide class C methods
#define HIDE_C(current) \
    HIDE_B(current) \
    FUNC_DEF_0(C, current, doSomething)

class C : public B {
public:
    template<typename _T = C>
    std::shared_ptr<_T> doSomething(){
        // something
        return A::getPtr<_T>();
    }
    HIDE_B(C); // hide B methods
};

int main() {
    auto obja = std::make_shared<A>();
    auto obj = std::make_shared<C>();
    obj->addChild(*obja)->doSomething();
}

编辑:固定尝试。为我编译。

代码语言:javascript
运行
复制
class A;

struct virtual_enable_shared_from_this_base :
    std::enable_shared_from_this<virtual_enable_shared_from_this_base> {
    virtual ~virtual_enable_shared_from_this_base() {}
};

#define HIDE_AMix(type) \
    using type::getPtr;

template<typename _T>
class AMix : public virtual virtual_enable_shared_from_this_base {
public:
    std::shared_ptr<_T> getPtr() {
        auto sptr = shared_from_this();
        return std::dynamic_pointer_cast<_T>(sptr);
    }
};

#define HIDE_BMix(type) \
    HIDE_AMix(type) \
    using type::addChild;

template<typename _T>
class BMix : public AMix<_T>{
public:
    std::vector<std::shared_ptr<A>> container;

    std::shared_ptr<_T> addChild(A* child){
        container.push_back(child->getPtr());
        return getPtr();
    }
};

#define HIDE_CMix(type) \
    HIDE_BMix(type) \
    using type::addChild;

template<typename _T>
class CMix : public BMix<_T>{
public:
    std::shared_ptr<_T> doSomething(){
        // something
        return getPtr();
    }
};


class A : public AMix<A> {
public:

};

class B : public A, public BMix<B> {
public:
    HIDE_AMix(BMix<B>);
    //using BMix<B>::getPtr;
    //using BMix<B>::addChild;
};

class C : public B, public CMix<C> {
public:
    HIDE_BMix(CMix<C>);
    //using CMix<C>::getPtr;
    //using CMix<C>::addChild;
    //using CMix<C>::doSomething;
};

int main() {
    auto obja = std::make_shared<B>();
    auto obj = std::make_shared<C>();
    obja->getPtr();
    obj->addChild(obja.get())->doSomething();
}

Edit2:这是修改模板的另一个版本。

票数 1
EN

Stack Overflow用户

发布于 2016-01-08 16:35:01

这里是一个例子,说明您可能正在尝试完成什么(虽然我不确定我100%理解您的需求或对此设计的推理)。希望能帮上忙..。

代码语言:javascript
运行
复制
#include <iostream>
#include <memory>
#include <vector>

class MyBase;
typedef std::shared_ptr<MyBase> MyBaseSharedPtr;

class MyBase : public std::enable_shared_from_this<MyBase> {
        public:
                MyBaseSharedPtr getPtr() { return shared_from_this(); }
                virtual MyBaseSharedPtr doSomething() { return getPtr(); };
                virtual MyBaseSharedPtr addChild(MyBaseSharedPtr child) { return getPtr(); };
};

class MyDerived1 : public MyBase {
        private:
                std::vector<MyBaseSharedPtr> container;
        public:
                MyBaseSharedPtr addChild(MyBaseSharedPtr child) {
                        container.push_back(child);
                        std::cout << "class MyDerived1: adding child\n";
                        return getPtr();
                };

                virtual MyBaseSharedPtr  doSomething() {
                        std::cout << "class MyDerived1: doing something\n";
                        return getPtr();
                }
};

class MyDerived2 : public MyDerived1 {
        public:
                MyBaseSharedPtr doSomething() {
                        std::cout << "class MyDerived2: doing something\n";
                        return getPtr();
                }
};

int main(void ) {
        MyBaseSharedPtr myBase = std::make_shared<MyBase>();
        MyBaseSharedPtr myDerived2 = std::make_shared<MyDerived2>();
        myDerived2->addChild(myBase)->doSomething();
        return 0;
}
票数 0
EN

Stack Overflow用户

发布于 2016-01-08 19:51:52

代码语言:javascript
运行
复制
template<typename _T>
shared_ptr<_T> allocate()
{
    shared_ptr<_T> ptr(new _T);
    // this may need to be changed to 
    // something like (*typename ptr.get()).weak_this
    // if the compiler won't accept a duck-typed _T::weak_this
    ptr.get()->weak_this = weak_ptr<_T>(ptr);
    return ptr;
}

class A
{
    weak_ptr<A> weak_this;
    friend shared_ptr<A> allocate<A>();

    public:
        shared_ptr<A> getPtr(){return weak_this.lock();}
        shared_ptr<A> doSomething()
        {
            // do something
            return getPtr();
        }
};
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34189711

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档