Learning to be Giant.

CPP Notes

|

这里记录一些C++学习当中遇到的零散的知识。不断更新。

宏的链接以及字符串宏

struct command
{
  char *name;
  void (*function) (void);
};

struct command commands[] =
{
  COMMAND (quit),
  COMMAND (help),
};

这段代码gcc -E产生的结果是

struct command commands[] = {
    {"quit", quit_command};
    {"help", help_command};
}

所以,#表示将宏的变量名解释成字符串,而##则表示两个部分的合并


remove const/volatile/reference

std::remove_cv<T>::type
std::remove_cv<const volatile int>::type

上面第一条语句可以去除掉T之前的const和volatile修饰,例如第二条语句。

相类似的还有std::remove_conststd::remove_volatilestd::remove_reference

我们可以这样使用这些:

// C++0x
using remove_reference_t = typename remove_reference<T>::type;

template in header

C++对于模板的处理就是当使用了模板之后依照模板的定义生成一个类或者函数,也就是说每一个引用模板的地方都应当能够看到模板的定义。所以,常用的一个方法就是将模板的实现放到头文件当中。为了将实现和声明相区别,可以这么做

// Foo.h
template <typename T>
struct Foo
{
    void doSomething(T param);
};

#include "Foo.tpp"

// Foo.tpp
template <typename T>
void Foo<T>::doSomething(T param)
{
    //implementation
}

delete constructor

class Foo {
  public:
    Foo() = delete;
}

通过这种方法显示的删除了类的constructor,并声明这个构造器是不应该使用的。在之前我们会使用将类的构造器设置成为private,用来避免用户使用。最常见的应用是在Singleton这种设计模式当中。通过将constructor设置为private,可以保证类只可以被在自己当中初始化一次,达到共享的目的。

然而,如果我们甚至不希望类自己可以调用自己的这个构造函数,那么我们可以将这种构造函数标记为delete。这种语法是与=default对应的。


inheritance constructor

C++0x引入了继承构造函数这一个新的特性,目的是解决当父类有许多构造函数,而子类并不需要对父类的构造函数有任何改动时仍需要照抄一遍父类构造函数的问题。例如,在以往的代码当中我们需要:

struct A {
  A(int i) {}
  A(double d, int i) {}
  A(float f, int i, const char* c) {} // ...
};
struct B : A {
  B(int i): A(i) {}
  B(double d, int i) : A(d, i) {}
  B(float f, int i, const char* c) : A(f, i, c){}
  // ...
  virtual void ExtraInterface(){}
};

事实上,在子类当中我们仅今天加了一个ExtraInterface(),但是却要写那么多的代码。为了解决这个问题,新标准引入了继承构造函数。现在我们可以这么写:

struct B : A {
  using A::A; // 继承构造函数
  // ...
  virtual void ExtraInterface(){}
};

当然,对于一般的函数来说我们也可以:

struct Base {
  void f(double i){ cout << "Base:" << i << endl; }
};
struct Derived : Base {
  using Base::f;
  void f(int i) { cout << "Derived:" << i << endl; }
};

这一条代码实现了在子类当中同时也使用父类的f(double)的重载目的。


name mangling and demangle

碰到一个很有意思的东西,在这个文件通常是不应该被引用的,但是教授实在是太牛逼了……主要调用到了其中的`__cxa_demangle()`方法。文件的[链接](http://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.4/a01163.html)。

相关Name Mangling Wiki。简单的讲就是说像C/C++这种变成语言是允许不同的变量拥有同样的变量名的,只要这些变量在不同的作用域当中。但是编译的时候就比较麻烦了,有时候可能会因为有相同的变量名导致一些问题,这时候比较直觉的解决方法就是将这些变量名变成不同的。这就是Name Mangling。而demangle方法其实就是当编译器已经将这种变量名给mangle成那个样子之后,再变回来的方法。

Comments