C++ 这是一个设计缺陷吗?
考虑两类C++ 这是一个设计缺陷吗?,c++,design-patterns,C++,Design Patterns,考虑两类 class A{ public: A(){ } ~A(){ } }; class AImpl : public A{ public: AImpl(){ a = new AInternal(); } AImpl(AInternal *a){ this->_a = a; }
class A{
public:
A(){
}
~A(){
}
};
class AImpl : public A{
public:
AImpl(){
a = new AInternal();
}
AImpl(AInternal *a){
this->_a = a;
}
~AImpl(){
if(a){
delete a;
a = null;
}
}
private:
AInternal *a;
};
我试图隐藏AInternal的实现,只公开A的接口。我在这里看到两件事
这个设计好吗。由于在设计方面非常缺乏经验,我看不出它的缺陷以及为什么它不好?我认为这是没有道理的。无论你在那里做什么,都应该在AImpl中完成。否则,在C++中可以这样做。 < p>代码相当钝,所以我担心在六个月内保持它。 你使用3个类使事情变得过于复杂。我想你要找的是。如果你要这样做,那么析构函数
~A
必须是虚拟的
我试图隐藏AInternal的实现,只公开A的接口
我想你是在尝试做类似的事情
以下是一个例子:
class IA {
public:
IA() {}
virtual ~IA() {}
virtual void dosth() =0;
};
class Factory {
private:
class A : public IA {
public:
A () {}
virtual ~A() {}
void dosth() { cout << "Hello World"; }
};
public:
Factory () {}
virtual ~Factory() {}
IA*newA() { return new A; }
};
您似乎结合了两个常见的设计功能:
1) 内部是一个“pimpl”。它提供了更好的封装,例如,如果需要向内部添加一个新字段,那么AImpl的大小不会改变。那很好
2) 是用于指示接口的基类。既然您讨论了上转换和下转换,我假设您需要动态多态性,这意味着您将拥有传递指针或对的引用的函数,并且在运行时,referelands实际上是AImpl类型的。这也很好,除了A的析构函数应该是虚拟的和公共的,或者是非虚拟的和受保护的
我认为这段代码没有其他设计问题。当然,您需要通过添加一些在AImpl中实现的纯虚拟成员函数来实际定义接口A。假设您计划这样做,那么使用空基类来实现在Java中由接口(如果您了解Java)提供服务的目的并没有错。通常,您会有一种工厂,它创建AImpl对象,并通过指针或对的引用返回它们(因此,向上转换它们)。如果客户机代码将直接创建AImpl对象,那么也可以,事实上,您可能根本不需要动态多态性。您可以改为进入模板
我不明白的是,你为什么要沮丧(也就是说,对AImpl*投A*)。这通常是个坏消息。因此,您的设计中可能存在一些问题,只有通过向我们展示更多的类定义,以及实际使用A和AImpl的客户机代码,我们才能发现这些问题。可能是可编译的?所以用户只看到了一个,而它什么也不做?遗产有什么好处谷歌搜索“pimpl”(指向实现的指针)。请注意,if(a)
检查析构函数是不必要的:首先,您可以删除空指针,其次,a
在调用析构函数时将永远不会为空(new
在失败时抛出异常)。+1。您可能希望为pImpl成员使用智能指针来增强异常安全性。我认为boost::scoped_ptr可能是理想的。cpp中的析构函数应该始终是虚拟的,而不仅仅是在这样的构造中。@qba:有三种不同用途的好选择:虚拟公共析构函数;非虚拟受保护析构函数;或者将该类记录为不用作具有动态多态性的基类。非常偶尔,为了特殊的技巧:私有析构函数+朋友。在本例中,该船可能使用了第三种选择。然而,在我看来,“你必须使你所有的析构函数都是虚拟的,因为我保留使用你的类进行动态多态性的权利,即使它不是为此而设计的”,这不是一个好的选择。我不同意。它不是一个真正的工厂,更像是一个包装器。我认为qba的要点是工厂可以通过返回一个抽象的基类指针来隐藏具体的类。这就是问题所要问的。这正是我所想的。
Factory f;
IA*a = f.newA();
a->dosth();
return 0;