编辑3:请务必在回答之前清楚地了解我的要求(有EDIT2和很多评论).有(或有)许多答案清楚地表明对问题的误解(我知道这也是我的错,对不起)
嗨,我class B: public virtual A {...}在C++中查看了关于虚拟继承()的问题,但没有找到我的问题的答案.
我知道虚拟继承存在一些问题,但我想知道的是虚拟继承被认为是一种好的设计.
我看到人们提到类似IUnknownor的接口ISerializable,而且该iostream设计也基于虚拟继承.那些是很好地利用虚拟继承的好例子,是因为没有更好的选择,或者因为在这种情况下虚拟继承是正确的设计?谢谢.
编辑:澄清,我问的是现实生活中的例子,请不要抽象.我知道虚拟继承是什么以及哪种继承模式需要它,我想知道的是何时它是做事的好方法而不仅仅是复杂继承的结果.
EDIT2:换句话说,我想知道钻石层次结构(这是虚拟继承的原因)何时是一个好的设计
我们有一个C++(MFC)的多线程桌面应用程序.目前开发人员使用CString或std :: string,可能取决于他们的心情.所以我们想选择一个实现(可能不是那两个).
MFC的CString基于写时复制(COW)习惯,有些人会声称这在多线程环境中是不可接受的(并且可能参考了这篇文章).我不相信这样的说法,因为原子计数器看起来非常快,并且这种开销在某种程度上可以通过减少内存重新分配来弥补.
我了解到std :: string实现依赖于编译器 - 它在MSVC中不是COW,但它是,或者是在gcc中.据我所知,新的C++ 0x标准将通过要求非COW实现并解决一些其他问题(例如连续的缓冲区要求)来解决这个问题.所以实际上std :: string看起来没有明确定义......
我不喜欢std :: string的一个简单示例:没有办法从函数返回一个字符串而没有过多的重新分配(复制构造函数如果按值返回,并且没有访问内部缓冲区来优化那么"返回通过引用"例如std::string& Result没有帮助".我可以使用CString执行此操作,方法是返回值(由于COW没有复制)或通过引用传递并直接访问缓冲区.再次,C++ 0x使用其右值引用进行救援,但我们不会在最近的特征中使用C++ 0x.
我们应该使用哪个字符串类?COW真的可以成为一个问题吗?是否有其他常用的字符串高效实现?谢谢.
编辑:我们目前不使用unicode,我们不太可能需要它.但是,如果有一些容易支持unicode的东西(不是以ICU为代价......),那将是一个加分.
我正在尝试在C++中实现多态迭代器.基本上,我需要这个能够应用一个过滤器,以便迭代器可以跳过一些项目,具体取决于相关的条件.所以我使用抽象接口创建了一个类似GoF的迭代器,这允许我从中派生一个过滤迭代器并实现所需的逻辑.我也更喜欢基于接口的迭代器而不是模板化的迭代器,因为它们允许隐藏实现而不会导致一堆鸭类模板.
但是,多态迭代器不能通过值返回(与STL迭代器相反),所以我必须传递指针,这很容易变得危险,就像在这种情况下,这似乎是合乎逻辑的,但会导致内存泄漏:
Iter* Collection::GetIter() {...} // new IterImpl
DoSomething(Iter*) {...} // doesn't do delete
DoSomething(Collection.GetIter()); // convenient, but wrong :\
Run Code Online (Sandbox Code Playgroud)
显而易见的解决方案是使用某种智能指针来控制迭代器的生命周期,但人们常说接口应该尽可能简单和通用,因此应该避免使用智能指针?
如果你在C++中使用过多态迭代器,那么这个问题是如何解决的?或者基于模板的迭代器是C++中唯一"好"的迭代方式?谢谢.
我有一种复杂的感觉static_cast,因为它是最安全的C++演员,但同时允许安全和不安全的转换,所以你必须知道上下文,说它是否真的安全或可能导致UB(例如,当铸造时到一个子类).
那么为什么没有更安全的明确演员呢?这是一个例子,它可能是有用的.在COM中,他们必须返回接口指针void** ppv,因此"必须"明确地进行转换
*ppv = (IInterface*) this;
Run Code Online (Sandbox Code Playgroud)
然后建议用更安全的C++演员代替
*ppv = static_cast<IInterface*>(this);
Run Code Online (Sandbox Code Playgroud)
但即使在static_cast这里也有意义吗?this是一个源自的类IInterface,所以人们可以简单地写
IInterface* p = this; // implicit conversion to base, safe for sure
*ppv = p;
Run Code Online (Sandbox Code Playgroud)
或使用像帮手一样的帮手
template<class T, class U>
T implicit_cast(U p) { return p; }
*ppv = implicit_cast<IInterface*>(this);
Run Code Online (Sandbox Code Playgroud)
那么,是否真的static_cast有时会被滥用,并且implicit_cast在某些情况下可以(应该?)替换它,或者我错过了什么?
编辑:我知道在COM中需要一个强制转换,但它不一定是static_cast,隐式强制转换就足够了.
我有一个类B需要A构造一个类的实例:
class B
{
B(A* a); // there is no default constructor
};
Run Code Online (Sandbox Code Playgroud)
现在我想创建一个包含B成员的类,所以我还需要添加A为成员并将其提供给B构造函数:
class C
{
C() : a(), b(&a) {}
A a; // 1. initialized as a()
B b; // 2. initialized as b(&a) - OK
};
Run Code Online (Sandbox Code Playgroud)
但问题是如果有人偶尔改变类中变量定义的顺序,它就会破坏
class C
{
C() : a(), b(&a) {}
B b; // 1. initialized as b(&a) while "a" uninitialized
A a; // too late...
};
Run Code Online (Sandbox Code Playgroud)
有没有一种很好的方法来解决这个问题,而无需修改类A和B …
c++ constructor initialization operator-precedence ctor-initializer
我想知道UML是否有助于描述重度模板化的代码.我知道UML(vector<T> <---- <<bind>> ---- vector<int>)中存在参数化类的概念,但这不足以描述我们可以使用模板的复杂鸭类关系.我总是可以在这些类之间建立关联,但在我看来它实际上并没有帮助理解它是如何工作的.
此外,考虑到例如STL库,算法通常被实现为函数,因此不太适合OOP模型,尽管它们仍然表现得非常类似于引入类之间的关联的对象.
那么,绘制UML图来描述这样的模板化代码是否有意义?如果是这样,哪种图表最有用 - 在"标准"OOP中,我看到大多数时候都使用类图,但是对于模板化代码,其他一些图表会更有用吗?如果UML不太适合,那我还能用什么呢?
假设以下头文件对应于例如共享库.导出的函数获取指向此标头中定义的自定义结构的指针:
// lib.h
typedef struct {
char c;
double d;
int i;
} A;
DLL_EXPORT void f(A* p);
Run Code Online (Sandbox Code Playgroud)
如果共享库是使用一个编译器构建的,然后是从使用另一个编译器构建的C代码中使用的,那么由于不同的内存对齐可能无法工作,因为C-struct中的内存对齐表明.那么,有没有办法让我的结构定义可以在同一平台上的不同编译器中移植?
我特别感兴趣的是Windows平台(显然它没有明确定义的ABI),但也很想了解其他平台.
这里已经有一些关于依赖管理器的问题,但在我看来,它们主要是关于构建系统,而我正在寻找一些纯粹的目标,使依赖性跟踪和解决方案更简单(我不一定有兴趣学习新的构建系统).
所以,通常我们有一个项目和一些与另一个项目共同的代码.这个公共代码被组织为一个库,所以当我想获得项目的最新代码版本时,我也应该从源代码控制中获取所有库.为此,我需要一个依赖项列表.然后,为了构建项目,我也可以重用这个列表.
我看过Maven和Ivy,但我不确定它们是否适合C++,因为它们看起来非常依赖于Java(即使可能有C++插件,我还没有找到人们推荐它们) .
我将其视为一个GUI工具,生成一些标准化的依赖列表,然后可以通过不同的脚本等进行解析.如果它可以与源代码控制集成(标记,获取带有依赖项的标记版本等)会很好,但这是可选的.
你有什么建议吗?也许我只是缺少一些东西,通常它是以其他方式完成而不需要这样的工具?谢谢.
抱歉这么长的问题,但我尽量保持清醒.这在某种程度上遵循了我之前关于C++中的字符串的问题.我试图找出如何从没有冗余内存分配的函数返回std :: string,而不依赖于NRVO.我不想依赖NRVO的原因是:
请注意,我需要一个C++ 03兼容的解决方案(不幸的是没有C++ 0x rvalue引用......)
最简单的方法是传递引用并执行std :: swap,就像这样
void test(std::string& res)
{
std::string s;
//...
res.swap(s);
}
Run Code Online (Sandbox Code Playgroud)
但是按价值返回比通过引用传递更自然且更方便,所以我想要实现的是:
std::string test()
{
std::string s;
//...
return SOMETHING(s);
}
Run Code Online (Sandbox Code Playgroud)
理想情况下,它只会swap使用"返回值",但我不知道如何在C++中执行此操作.有auto_ptr已经移动而不是复制,我实际上可以使用auto_ptr<string>,但我想避免动态分配字符串对象本身.
我的想法是以某种方式"标记"一个字符串对象,它从函数返回以允许在返回时调用复制构造函数时移动其数据.所以我最终得到了这个代码,它完全符合我的要求:
struct Str
{
struct Moveable
{
Str & ref;
explicit Moveable(Str & other): ref(other) {}
};
Str() {}
Str(const std::string& other) : data(other) {} // copy
Str(Moveable& other) { data.swap(other.ref.data); } // move
Moveable …Run Code Online (Sandbox Code Playgroud) 我可以用这种方式编写模板化函数
template<class T> void f(T x) {...}
Run Code Online (Sandbox Code Playgroud)
或者这样
template<class T> void f(T const& x) {...}
Run Code Online (Sandbox Code Playgroud)
我猜第二个选项可以更加优化,因为它明确地避免了副本,但我怀疑它也可能因某些特定类型T(例如仿函数?)而失败.那么,什么时候应该使用第一个选项,何时使用第二个选项?还有这个boost::call_traits<T>::param_type和boost::reference_wrapper那个在我之前的问题的答案,但人们不到处使用它们,是吗?这有经验法则吗?谢谢.
c++ ×9
templates ×2
c ×1
casting ×1
constructor ×1
iterator ×1
oop ×1
polymorphism ×1
portability ×1
static-cast ×1
stl ×1
string ×1
swap ×1
type-safety ×1
uml ×1
windows ×1