小编Rom*_*n L的帖子

当虚拟继承是一个好的设计?

编辑3:请务必在回答之前清楚地了解我的要求(有EDIT2和很多评论).有(或有)许多答案清楚地表明对问题的误解(我知道这也是我的错,对不起)

嗨,我class B: public virtual A {...}在C++中查看了关于虚拟继承()的问题,但没有找到我的问题的答案.

我知道虚拟继承存在一些问题,但我想知道的是虚拟继承被认为是一种好的设计.

我看到人们提到类似IUnknownor的接口ISerializable,而且该iostream设计也基于虚拟继承.那些是很好地利用虚拟继承的好例子,是因为没有更好的选择,或者因为在这种情况下虚拟继承正确的设计?谢谢.

编辑:澄清,我问的是现实生活中的例子,请不要抽象.我知道虚拟继承是什么以及哪种继承模式需要它,我想知道的是何时它是做事的好方法而不仅仅是复杂继承的结果.

EDIT2:换句话说,我想知道钻石层次结构(这是虚拟继承的原因)何时是一个好的设计

c++ multiple-inheritance virtual-inheritance

26
推荐指数
1
解决办法
6933
查看次数

在C++中使用哪些字符串类?

我们有一个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++ string multithreading copy-on-write

17
推荐指数
2
解决办法
2661
查看次数

C++中的多态迭代器

我正在尝试在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++中唯一"好"的迭代方式?谢谢.

c++ polymorphism iterator

16
推荐指数
1
解决办法
5130
查看次数

static_cast被误用了吗?

我有一种复杂的感觉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,隐式强制转换就足够了.

c++ casting static-cast type-safety

14
推荐指数
1
解决办法
756
查看次数

依赖类作为其他类成员

我有一个类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)

有没有一种很好的方法来解决这个问题,而无需修改类AB …

c++ constructor initialization operator-precedence ctor-initializer

10
推荐指数
2
解决办法
947
查看次数

UML对描述模板化代码有用吗?

我想知道UML是否有助于描述重度模板化的代码.我知道UML(vector<T> <---- <<bind>> ---- vector<int>)中存在参数化类的概念,但这不足以描述我们可以使用模板的复杂鸭类关系.我总是可以在这些类之间建立关联,但在我看来它实际上并没有帮助理解它是如何工作的.

此外,考虑到例如STL库,算法通常被实现为函数,因此不太适合OOP模型,尽管它们仍然表现得非常类似于引入类之间的关联的对象.

那么,绘制UML图来描述这样的模板化代码是否有意义?如果是这样,哪种图表最有用 - 在"标准"OOP中,我看到大多数时候都使用类图,但是对于模板化代码,其他一些图表会更有用吗?如果UML不太适合,那我还能用什么呢?

c++ oop templates uml

10
推荐指数
1
解决办法
1001
查看次数

跨编译器的C结构对齐和可移植性

假设以下头文件对应于例如共享库.导出的函数获取指向此标头中定义的自定义结构的指针:

// 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),但也很想了解其他平台.

c windows portability

10
推荐指数
1
解决办法
2223
查看次数

C++的源代码依赖项管理器

这里已经有一些关于依赖管理器的问题,但在我看来,它们主要是关于构建系统,而我正在寻找一些纯粹的目标,使依赖性跟踪和解决方案更简单(我不一定有兴趣学习新的构建系统).

所以,通常我们有一个项目和一些与另一个项目共同的代码.这个公共代码被组织为一个库,所以当我想获得项目的最新代码版本时,我也应该从源代码控制中获取所有库.为此,我需要一个依赖项列表.然后,为了构建项目,我也可以重用这个列表.

我看过Maven和Ivy,但我不确定它们是否适合C++,因为它们看起来非常依赖于Java(即使可能有C++插件,我还没有找到人们推荐它们) .

我将其视为一个GUI工具,生成一些标准化的依赖列表,然后可以通过不同的脚本等进行解析.如果它可以与源代码控制集成(标记,获取带有依赖项的标记版本等)会很好,但这是可选的.

你有什么建议吗?也许我只是缺少一些东西,通常它是以其他方式完成而不需要这样的工具?谢谢.

c++ dependency-management

9
推荐指数
1
解决办法
3612
查看次数

STL交换回报?

抱歉这么长的问题,但我尽量保持清醒.这在某种程度上遵循了我之前关于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)

c++ swap stl return-value-optimization

8
推荐指数
1
解决办法
1028
查看次数

模板传递值或const引用或...?

我可以用这种方式编写模板化函数

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_typeboost::reference_wrapper那个在我之前的问题的答案,但人们不到处使用它们,是吗?这有经验法则吗?谢谢.

c++ templates pass-by-reference pass-by-value

7
推荐指数
3
解决办法
6708
查看次数