非虚拟接口惯用法描述了虚拟方法是非公共自定义点的方式,公共方法是非虚拟方法,以允许基类始终控制如何调用自定义点.
这是一个优雅的习语,我喜欢使用它,但如果派生类本身就是一个基类,它是如何工作的
迭代向量的元素时,最好使用迭代器而不是索引(请参阅为什么使用迭代器而不是数组索引?).
std::vector<T> vec;
std::vector<T>::iterator it;
for ( it = vec.begin(); it != vec.end(); ++it )
{
// do work
}
Run Code Online (Sandbox Code Playgroud)
但是,可能需要在循环体中使用索引.考虑到性能和灵活性/可扩展性,在这种情况下,下列哪一项更可取?
std::vector vec;
size_t i;
for ( i = 0; i < vec.size(); ++i )
{
// use i
}
std::vector vec;
std::vector::iterator it;
for ( it = vec.begin(); it != vec.end(); ++it )
{
size_t i = it - vec.begin();
// use i
}
std::vector vec; std::vector::iterator it; for ( it = …
或者是吗?
面向对象的设计是否应该使用默认情况下公开成员数据的语言结构,如果有一个同样有用的结构可以正确隐藏数据成员?
编辑:其中一个响应者提到,如果没有不变量,可以使用结构.这是一个有趣的观察结果:结构是一种数据结构,即它包含相关数据.如果结构中的数据成员是相关的,那么总是存在不变量吗?
我想在C++中实现数据访问对象模式,但最好不使用多继承和/或boost(我的客户不喜欢).
你有什么建议吗?
我如何'潜水'一个指向动态分配的整数数组的int*并将其表示为一个固定的int []数组?换句话说,如果我潜入一个int*它显示地址和int指向,但我希望看到所有整数的数组.
在C++中,接口可以由类实现,其所有方法都是纯虚拟的.
这样的类可以是库的一部分,用于描述对象应该实现哪些方法以便能够与库中的其他类一起使用:
class Lib::IFoo
{
public:
virtual void method() = 0;
};
Run Code Online (Sandbox Code Playgroud)
:
class Lib::Bar
{
public:
void stuff( Lib::IFoo & );
};
Run Code Online (Sandbox Code Playgroud)
现在我想使用类Lib :: Bar,所以我必须实现IFoo接口.
为了我的目的,我需要一个完整的相关类,所以我想使用一个基类来保证使用NVI习语的常见行为:
class FooBase : public IFoo // implement interface IFoo
{
public:
void method(); // calls methodImpl;
private:
virtual void methodImpl();
};
Run Code Online (Sandbox Code Playgroud)
非虚拟接口(NVI)习惯用法应该拒绝派生类覆盖实现的公共行为的可能性FooBase::method(),但是由于IFoo使其成为虚拟,所以派生类似乎都有机会覆盖FooBase::method().
如果我想使用NVI成语,除了已经建议的pImpl成语之外我还有什么选择(感谢space-c0wb0y).
我已经写了枚举的序列化的函数模板/从我们的流类(是的,我知道的boost ::序列化,但它不是我的情况的一个选项).按照惯例,我们公司的枚举序列化为int:
template<typename T>
Stream& operator<<( Stream& s, T const& value )
{
s << ( int ) value;
}
template<typename T>
Stream& operator>>( Stream& s, T & value )
{
int v;
s >> v;
value = (T) v;
}
Run Code Online (Sandbox Code Playgroud)
这些是简单的模板,它们也可以在我的函数模板中很好地工作,以便(de)序列化枚举项的向量.我担心它们过于通用,即它们也适用于T那些不能enums但可以转换为/来自的类型int.我可以改进枚举序列化模板(或者矢量序列化模板)以确保它们仅适用于enums的向量吗?
抽象基类(接口类)通常具有抽象的所有成员函数.但是,我有几种情况,其中使用由调用接口的抽象方法组成的成员函数.我可以在派生但仍然是抽象的类中实现它们,或者我可以将这些方法实现为接口类的非抽象非虚方法.
在接口类中实现方法是否存在设计方面的问题?是不好的风格,如果是这样,为什么?
静态方法是否一样?
例如
class IFoo
{
public:
virtual ~IFoo();
virtual double calcThis( InputType p ) const = 0;
virtual double calcThat( InputType p ) const = 0;
double calcFraction( InputType p ) { return calcThis( p ) / calcThat( p ); }
static BarType bar( InputType p );
};
class MyFoo : public IFoo
{
public:
// implements IFoo
virtual double calcThis( InputType p ) const;
// implements IFoo
virtual double calcThat( InputType p ) const;
};
Run Code Online (Sandbox Code Playgroud)
与
class …Run Code Online (Sandbox Code Playgroud) 作为对口C++编码指南102,它的萨特和Alexandrescu的101个指引你违反或忽视最常用的,为什么?
我试图func用C++样式函数覆盖库中的C风格函数(),接受不同的参数,如下面的代码所示.
我将test.cpp编译成共享库libtest.so,并编译main.cpp并将其与libtest.so库链接.这一切都有效,直到我得到的链接步骤
undefined reference to 'func(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)'.
有人可以解释为什么链接器无法解析C++函数?我用nm检查了两个函数确实在库中.使用intel和g ++编译器时会发生链接器错误.
test.h:
extern "C" {
int func( char* str, int size );
}
#include <string>
int func( std::string str );
Run Code Online (Sandbox Code Playgroud)
TEST.CPP:
#include <stdio.h>
#include <string>
#include "test.h"
int func( char *buf, int size )
{
return snprintf( buf, size, "c-style func" );
}
int func( std::string& str )
{
str = "c++-style func";
return str.size();
}
Run Code Online (Sandbox Code Playgroud)
main.cpp中:
#include <iostream>
#include <string>
#include "test.h"
int main()
{
char …Run Code Online (Sandbox Code Playgroud) 我想知道是否可以编写一个函数,将序列拆分为返回为 的子序列IEnumerables,其中如果当前T等于T该子序列的第一个子序列,则子序列结束,而不缓存子序列。我已经成功编写了一个在列表中构建当前子序列的实现。
所以我希望能够实现功能
IEnumerable<IEnumerable<T>> SplitInSubsequences(IEnumerable<T> sequence)
{
...
}
Run Code Online (Sandbox Code Playgroud)
不使用一些临时集合List<T>来缓存当前子序列。
为了说明分割操作应该做什么:
var sequence = new List<int>{ 1,2,3,1, 4,6,1,5,4, 1,3,1, 2,2};
var subsequences = SplitInSubsequences( sequence ).ToList();
Assert.That(subsequences.Length,Is.EqualTo(4));
Assert.That(subsequences[0],Is.EquivalentTo(new List<int>{1,2,3,1});
Assert.That(subsequences[1],Is.EquivalentTo(new List<int>{4,6,6,5,4});
Assert.That(subsequences[2],Is.EquivalentTo(new List<int>{1,3,1});
Assert.That(subsequences[3],Is.EquivalentTo(new List<int>{2,2});
Run Code Online (Sandbox Code Playgroud)
请注意,原则上仅需要存储每个子序列的第一个元素以便与当前元素进行比较。