在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 ++语言结构是否有更好的或更有效的方法来实现这种效果?
答案 0 :(得分:0)
是的,这是可能的。其中一个可能的例子是:
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>
答案 1 :(得分:-1)
您可以在基类中实现虚拟接口
但是,如果您真的想委派,那么您可以重载operator->
以委派所有呼叫。
您将不再需要转发方法:
#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();
}