虚拟类和封装存在一些问题。 请考虑以下C ++程序的最小示例:
#include <iostream>
class IConnection
{
public:
virtual void connect() = 0;
virtual std::string recv() = 0;
virtual void disconnect() = 0;
virtual ~IConnection() {}
};
class ConcreteConnection: public IConnection
{
public:
ConcreteConnection(): m_connected(false) {}
void connect() { m_connected = true; }
std::string recv() { return "Received some text."; }
void disconnect() { m_connected = false; }
private:
bool m_connected;
};
class Container
{
public:
Container() { m_connection = NULL; }
void SetConnection(IConnection *connection) { m_connection = connection; };
void GetData() { std::cout << m_connection->recv() << std::endl; }
~Container() { delete m_connection; }
private:
IConnection *m_connection;
};
int main(void)
{
Container container;
ConcreteConnection *connection = new ConcreteConnection();
container.SetConnection(connection);
container.GetData();
return 0;
}
这个简单的例子工作正常,但我并不完全满意。该 容器对象应该拥有连接,而不会受到打扰 接口IConnection的具体实现。这就是我创造的原因 容器外部的ConcreteConnection对象。我不喜欢的是 我必须传递连接的指针或引用。我想通过 connection-object的副本,因此main-function没有任何副本 在将连接对象传递给之后操纵或删除连接对象的机会 容器。但据我所知,不可能通过副本 连接,而不告诉容器具体实现 IConnection它属于。
那么你有什么想法解决这个问题吗?是否有可能传递一个 将对象复制到任何函数而不告诉函数到哪个 对象所属接口的具体实现?
我对C ++和OOP都比较陌生,所以不要犹豫,告诉我,如果我的话 类结构是完全错误的,这种情况不会发生在现实生活中 编程代码(以及它应该如何工作)。
提前致谢。
答案 0 :(得分:2)
以下是我在现代C ++中的写法:
#include <memory>
#include <type_traits>
class Container
{
std::unique_ptr<IConnection> ptr;
explicit Container(IConnection * p) : ptr(p) { }
public:
template <typename T, typename ...Args>
static typename std::enable_if<std::is_base_of<IConnection, T>::value, Container>::type
make(Args &&... args)
{
return Container(new T(std::forward<Args>(args)...));
}
};
用法:
int main()
{
auto c1 = Container::make<ConcreteConnection>();
auto c2 = Container::make<TCPConnection>("127.0.0.1", 8080);
auto c3 = Container::make<LocalPipeConnection>("/tmp/pipe");
}
答案 1 :(得分:0)
以这种方式思考:从抽象类继承的所有不同的具体类都有不同的成员等。所以,除非你告诉编译器你传递了什么样的对象,它将如何知道有多少内存分配等?
因此,当您编写一个将抽象类指针作为参数的函数时,编译器确切地知道需要为该参数分配多少空间:一个指针的大小。如果您尝试使参数成为抽象类的实例而不是指针,则编译器不知道要分配多少内存,因为它取决于将哪个派生类传递给函数。