我想知道是否存在这样的伪代码:
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
。
发布于 2016-01-11 03:25:28
这种概念将被扩展方法所涵盖,这些方法存在于类定义之外,不违反类权限,但可以像方法一样调用.它存在于C#中,但目前不存在于C++中。C#中的代码如下所示:
// 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的每个继承都有自己的函数定义,因为函数不是继承的方法,而是直接应用于每个相关类型。
反对的理由是,扩展会以通常不需要的功能污染对象,而独立的模板函数也会做同样的事情。问题是,按照这种逻辑:
int main(){
A obja = new A();
C obj = new C();
obj->getPtr()->addChild(obja)->doSomething()
}
最后看起来就像
int main(){
A obja = new A();
C obj = new C();
doSomething(addChild(getPtr(obj),obja)); //eyeroll.
}
您仍然需要声明模板函数,如
// 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++类需要具有非继承的专用公共方法,这些方法不在当前访问权限的公共、私有和受保护或模板功能的范围之内。
我会很高兴找到一个很好的方法来摆脱操作员链。
既然我浪费了你的时间,我就做了一个尝试:
#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();
}
编辑:固定尝试。为我编译。
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:这是修改模板的另一个版本。
发布于 2016-01-08 16:35:01
这里是一个例子,说明您可能正在尝试完成什么(虽然我不确定我100%理解您的需求或对此设计的推理)。希望能帮上忙..。
#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;
}
发布于 2016-01-08 19:51:52
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();
}
};
https://stackoverflow.com/questions/34189711
复制相似问题