【问题标题】:How do you implement "delegation" for classes efficiently in C++?如何在 C++ 中有效地为类实现“委托”?
【发布时间】:2016-05-08 18:03:09
【问题描述】:

在Objective C 中,该语言已内置支持将类委托给其他类。 C++ 没有这样的特性(一个类作为另一个类的代表)作为语言的一部分。一种模仿的方法是以这种方式分离声明和实现:

在头文件a.h中:

class AImpl;

class A
{
public:
     A();

     void f1();
     int f2(int a, int b); 
     // A's other methods...
private:
    AImpl *mImpl;
};

.cpp(实现文件)中:

#include "a.h"

class AImpl
{
public:
     AImpl();
     // repeating the same method declarations from A
     void f1();
     int f2(int a, int b); 
     // AImpl's other methods
};

AImpl::AImpl()
{
}

void AImpl:f1()
{
    // actual implemetation
}

int AImpl::f2(int a, int b)
{
    // actual implmentation
}

// AImpl's  other methods implementation

A::A()
{
     mImpl = new AImpl();
}

// A's "forwarder"

void A::f1()
{
    mImpl->f1();
}

int A::f2(int a, int b)
{
    return mImpl->f2(a, b);
}

// etc.

这需要在类中手动创建所有“转发器”函数,这些函数将委托给另一个类来完成实际工作。乏味,至少可以这么说。

问题是:有没有一种更好的或更高效的方法来使用模板或其他 C++ 语言结构来实现这种效果?

【问题讨论】:

  • 您可以在标头中声明一个纯接口,并声明一个工厂函数,而不是所有这些转发。在实现文件中有一个实现接口的类,以及工厂的实现。假设客户端代码不应该能够有意义地扩展类。
  • 我不认为有,但我会等待比我更有知识的人来纠正我。
  • 我正要写一个关于如何在 C++ 中委托函数的完整列表,但我发现有人已经这样做了:stackoverflow.com/questions/9568150/what-is-a-c-delegate 投票关闭为重复
  • 我澄清了这个问题——我对类级委派特别感兴趣,而不是函数级委派。

标签: c++ delegation


【解决方案1】:

是的,这是可能的。一个可能的例子是:

struct WidgetDelegate
{
    virtual ~WidgetDelegate() {}
    virtual void onNameChange(std::string newname, std::string oldname) {}
};

class Widget
{
public:
    std::shared_ptr<WidgetDelegate> delegate;
    explicit Widget(std::string name) : m_name(name){}
    void setName(std::string name) {
        if (delegate) delegate->onNameChange(name, m_name);
        m_name = name;
    }
private:
    std::string m_name;
};

用法:

class MyWidgetDelegate : public WidgetDelegate
{
public:
    virtual void onNameChange(std::string newname, std::string oldname) {
        std::cout << "Widget old name: " << oldname << " and new name: " << newname << std::endl;
    }
};

int main()
{
    Widget my_widget("Button");
    my_widget.delegate = std::make_shared<MyWidgetDelegate>();
    my_widget.setName("DoSomeThing");   
    return 0;
}

必需的包括:

#include <string>
#include <iostream>
#include <memory>

【讨论】:

    【解决方案2】:

    您可以在基类中实现虚拟接口。
    但是,如果你真的想委托,那么你可以重载operator-&gt; 来委托所有调用。
    您将不再需要转发方法:

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    class AImpl;
    
    class A
    {
        public:
            A();
    
            //Overloading operator -> delegates the calls to AImpl class
            AImpl* operator->() const { return mImpl; }
    
        private:
            AImpl *mImpl;
    };
    
    class AImpl
    {
        public:
            void f1() { std::cout << "Called f1()\n"; }
            void f2() { std::cout << "Called f2()\n"; }
    };
    
    A::A()
    {
        mImpl = new AImpl();
    }
    
    int main()
    {
        A a;
        a->f1(); //use a as if its a pointer, and call functions of A
    
        A* a1 = new A();
        (*a1)->f2();
    }
    

    【讨论】:

    • 老实说,使用a 好像它是一个指针 当它不是有点违反直觉,我想它不会帮助读者/维护者代码。我的两分钱。
    猜你喜欢
    • 2019-10-07
    • 2020-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多