1函数模板不支持偏特化
2类内部的typedef 必须放在最前面,不然没法用:
疑问:为什么类声明处定义的函数体中能出现在后面在声明的成员变量??因为C++对于成员函数函数体的解析是放在整个类声明完毕之后的.
3const vs nonconst member function
注意成员函数的const属性限定并不出现在重载决议中,如果在一个基类中定义了一个成员函数memfunc1(), 然后定义了它的nonconst version
则在派生类里面无论定义一个 const memberfunc1()还是nonconst memberfunc1(),都会覆盖基类的那两个函数,比如下面代码:
class Base{
public:
virtual void sayHello()
{
static int local = 0;
local++;
a = local;
cout << "hello from nonconst"<<endl;
cout << a;
}
virtual void sayHello() const
{
cout << "hello from const" << endl;
}
private:
int a;
};
class Derived:public Base
{
public:
void sayHello()
{
cout << "derived" << endl; //派生类的const 对象再也调用不了sayHello函数了
}
};
关于这一点,可以参考访问控制权限类似的设计,因为名字决议是先于访问控制权限的检查的
4函数返回值并不在name mangling之列,所以从这个角度讲,函数调用也没有达到绝对的类型安全(返回值搞错了的话编译器是检查不出来的)
5 pointer to data member
首先要意识到这是一种指针(可以赋值为nullptr,那样用%d就输出 -1),用printf(%d)输出的就是所指成员变量在类中的偏移
#include<iostream> using namespace std; class Point3d { public: //virtual ~Point3d(){} //static Point3d origin; float x; float y; float z; }; struct Base1{int val1;}; struct Base2{int val2;}; struct Derived:Base1, Base2{}; void func1(int Derived::*dmp, Derived* p, const Derived& p2) { cout << p->*dmp << endl; cout << p2.*dmp << endl; } int main(int argc, char** argv[]) { Point3d p; float Point3d::*p1 = nullptr; float Point3d::*p2 = &Point3d::x; if(p1 == p2) cout << "YES"; printf("%d %d\n", p1, p2); Derived d1, d2; d1.val1 = 2, d1.val2 = 3; d2.val1 = 4, d2.val2 = 5; func1(&Derived::val1, &d1, d2); return 0; }
6关于调用虚函数的开销
区分三种类型:普通对象,引用类型,指针类型
指针不用说,额外增加是间接性很容易理解
引用类型调用函数的格式看起来和对象类型是一致的,但调用虚函数的开销却和指针一样
普通对象调用虚函数就像调用一般的函数一样,没有额外开销
7violatile关键字修饰的作用
被volatile关键字所修饰的变量,只不过是每次使用的时候,都必须从(原始的)(存储变量内容的) 内存 中读取数据,写数据也应该要保证写到内存中去
不允许寄存器优化
8基于函数指针和直接的函数名的调用方式上完全一样:
这完全是为了方便.
还有一点,函数地址和数据地址是两个东西(一个指示代码段,一个指示数据段),所以把void*类型变量赋值成函数指针是错误的做法!
9 In C++, tentative definitions are not supported
10 One difference between C and C++, then, is the relative unimportance of the BSS data segment in C++. All global objects within C++ are treated as initialized.