为什么这样:
#include <string>
#include <iostream>
using namespace std;
class Sandbox
{
public:
Sandbox(const string& n) : member(n) {}
const string& member;
};
int main()
{
Sandbox sandbox(string("four"));
cout << "The answer is: " << sandbox.member << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
给出输出:
答案是:
代替:
答案是:四
我在Curiously Recurring Template Pattern上阅读的所有材料似乎都是一层继承,即Base和Derived : Base<Derived>.如果我想更进一步怎么办?
#include <iostream>
using std::cout;
template<typename LowestDerivedClass> class A {
public:
LowestDerivedClass& get() { return *static_cast<LowestDerivedClass*>(this); }
void print() { cout << "A\n"; }
};
template<typename LowestDerivedClass> class B : public A<LowestDerivedClass> {
public: void print() { cout << "B\n"; }
};
class C : public B<C> {
public: void print() { cout << "C\n"; }
};
int main()
{
C c;
c.get().print();
// B b; // Intentionally bad syntax,
// …Run Code Online (Sandbox Code Playgroud) using namespace boost;
class A {};
class B : public A {};
class X {
virtual shared_ptr<A> foo();
};
class Y : public X {
virtual shared_ptr<B> foo();
};
Run Code Online (Sandbox Code Playgroud)
返回类型不是协变的(因此它们也不合法),但如果我使用的是原始指针,它们就会出现.如果有的话,解决这个问题的普遍接受的习惯是什么?
我有对象在其构造函数中创建其他子对象,传递'this',以便子进程可以将指针保存回其父对象.我在编程中广泛使用boost :: shared_ptr作为std :: auto_ptr或原始指针的更安全的替代品.因此,孩子将拥有诸如的代码shared_ptr<Parent>,并且boost提供shared_from_this()父母可以给孩子的方法.
我的问题是shared_from_this()不能在构造函数中使用,这不是真正的犯罪,因为"this"不应该在构造函数中使用,除非你知道你正在做什么并且不介意限制.
Google的C++样式指南指出构造函数应该只将成员变量设置为其初始值.任何复杂的初始化都应该采用显式的Init()方法.这解决了"这个构造函数"问题以及其他一些问题.
困扰我的是,现在使用代码的人必须记住每次构造一个对象时都调用Init().我可以想到强制执行此操作的唯一方法是通过断言已经在每个成员函数的顶部调用了Init(),但这样编写繁琐且执行起来很麻烦.
那边有什么习惯用法可以解决这个问题吗?
如果我有一个带有2个必需参数和4个可选参数的构造函数,如果我使用默认参数(我不喜欢因为它很差),我怎么能避免编写16个构造函数,甚至编写10个左右我必须编写的构造函数自文档)?有没有使用模板的习语或方法我可以使用它来减少繁琐?(更容易维护?)
template<typename T>
class Base
{
protected:
Base() {}
T& get() { return t; }
T t;
};
template<typename T>
class Derived : public Base<T>
{
public:
Base<T>::get; // Line A
Base<T>::t; // Line B
void foo() { t = 4; get(); }
};
int main() { return 0; }
Run Code Online (Sandbox Code Playgroud)
如果我注释掉A行和B行,这段代码在Visual Studio 2008下编译得很好.但是当我在GCC 4.1下用A和B行编译时,我得到了以下错误:
在成员函数'void Derived :: foo()'中:
错误:'t'未在此范围内声明
错误:没有依赖于模板参数的'get'参数,因此'get'的声明必须是可得到
为什么一个编译器需要A行和B行而另一个编译器不需要?有没有办法简化这个?换句话说,如果派生类使用基类中的20个东西,我必须为从Base派生的每个类放置20行声明!有没有办法解决这个问题?
class A1 { public: friend class B; }
class A2 { private: friend class B; }
Run Code Online (Sandbox Code Playgroud)
有什么区别?
class Foo
{
public:
explicit Foo() {}
explicit Foo(Foo&) {}
};
Foo d = Foo();
Run Code Online (Sandbox Code Playgroud)
错误:没有用于调用'Foo :: Foo(Foo)'的匹配函数
我试图改变Foo(Foo&),以Foo(Foo)作为错误提示,这AFAIK不是有效的构造,果然,我得到:
错误:构造函数无效; 你可能意味着'Foo(const Foo&)'
是什么赋予了?我该如何解决这个问题?(顺便说一下,这是GCC)
我希望在我的一个OpenGL项目中大力转向模板,主要是为了娱乐和学习体验.我计划仔细观察可执行文件的大小,看看有多少臭名昭着的膨胀发生.目前,当我支持速度时,我的Release版本的大小约为580 KB,当我喜欢大小时,我的大小为440 KB.
是的,这是一个很小的项目,实际上即使我的可执行文件大小只有10倍,它仍然会达到5 MB左右,按照今天的标准来看似乎不大......或者是它?这让我想到了我的问题.速度是否与大小成正比,或者是否存在特定阈值的跳跃和平稳期,我应该保持低于阈值?(如果是这样,具体的阈值是多少?)
就我而言,
#include <boost/mpl/list.hpp>
#include <algorithm>
namespace mpl = boost::mpl;
class RunAround {};
class HopUpAndDown {};
class Sleep {};
template<typename Instructions> int doThis();
template<> int doThis<RunAround>() { /* run run run.. */ return 3; }
template<> int doThis<HopUpAndDown>() { /* hop hop hop.. */ return 2; }
template<> int doThis<Sleep>() { /* zzz.. */ return -2; }
int main()
{
typedef mpl::list<RunAround, HopUpAndDown, Sleep> acts;
// std::for_each(mpl::begin<acts>::type, mpl::end<acts>::type, doThis<????>);
return 0;
};
Run Code Online (Sandbox Code Playgroud)
我该如何完成?(我不知道我是否应该使用std :: for_each,只是基于另一个答案的猜测)
c++ ×10
boost ×3
constructor ×3
templates ×3
gcc ×2
shared-ptr ×2
boost-mpl ×1
covariance ×1
crtp ×1
explicit ×1
friend ×1
idioms ×1
performance ×1
private ×1
public ×1
return-value ×1
temporary ×1