有段时间没上blog了,正好晚上有点时间,来更新下吧;)
最近抽空忙着温习知识,为实习做准备。cpp是吃饭的家伙,必然要烂熟于心才行。所以抽空把primer的部分章节又看了一遍,把一些平时不怎么用的,快要淡出记忆的东西给找了回来。
静态常量型整形变量才能在类声明中赋初值
.H
class A
{
public:
int hello(int i) {return i;}
int HookShot;
private:
static const int i = 10; // okay
static int n = 5; // wrong
static vector<int> vec(10); // wrong
static const float f = 1.0f; // wrong
}
.CPP
float A::f = 1.0f; // okay
vector<int> A::vec(n) // okay
vector<int> A::vec(i) // okay
函数指针不能被赋值为成员函数的地址,即使返回类型和参数表完全匹配。必须指定类类型
int (A::* pfunc) (int) = A::hello;
A a;
(a.*pfunc)(3); // 不能漏掉*,否则错误
指向成员变量的指针:
int A::* pvar = & A::HookShot; // 必须有&
cout<<a.*pvar;
指向类成员的指针语法不能被用来引用类的静态成员。静态类成员是属于该类的全局对象和函数,它们的指针是普通指针
用union来测试cpu是big_endian还是little_endian
union test
{
int a;
char b;
};
bool IsLittle_Endian()
{
union test t;
t.a = 1;
return (t.b == 1); // true means little_endian 0×00…1 1为低位,0为高位
}
—-2006/4/10
在类体中,后声明的成员不能被先声明的成员声明使用
在类定义中用到的名字必须在使用前首先被声明。这个规则有两种例外的情况:第一个例外是对于被用在inline 成员函数定义中的名字;第二个例外是于被用作缺省实参的名字。
用在类定义中的名字除了上述2种例外,其解析过程按照:
1、在该名字之前有否相关声明(在类域中查找)
2、如果1没有查找成功,则在类定义之前的名字空间中查找相关声明
被用在类成员函数定义中的名字的解析过程:
1 在成员函数局部域中的声明首先被考虑
2 如果在步骤1 中的解析不成功则考虑所有的类成员声明
3 如果在步骤2 中的解析不成功则考虑在成员函数定义之前的名字空间域中出现的声明
私有成员是指这样的成员,它只能在该类的成员或友元定义中被访问。除非外围类被声明为嵌套类的友元,否则它没有权利访问嵌套类的私有成员
class A
{
public:
static void GreetingsFromA() {cout<<"Outer";}
}
class B
{
public:
A obj; // this obj will be an instance of A (outer)
class A
{
public:
static void GreetingsFromA() {cout<<"Inner";}
}
A objobj; // this obj will be an instance of A (inner)
}
如果外围类A的名字改为别的,则A obj;这句话将会报错。
如果想要使用内部类来声明一个变量,则必须将该句声明放在内部类的声明之后。
局部类的成员通常都是public的
—-2006/4/11
派生类中如果出现和基类中名字相同的成员函数或成员变量,则在派生类中相对应的基类版本成员变量或成员函数将会不可见。除非使用类域来显式指出
之所以相同函数名的函数不能直接在基类和派生类之间重载,是因为重载函数必须都出现在同一个域中。而基类的函数属于基类的域,派生类的函数属于派生类的域
—-2006/4/12
Using 基类::函数名
在派生类的声明中添加,以此来实现派生类对基类函数的重载
如果基类和派生类都声明了一个相同名字的非虚拟函数,则通过基类指针该函数总是调用基类版本
基类中的静态成员将只有一个,无论该基类被继承多少次
友元关系不会被继承
构造函数调用顺序:
基类构造函数(如果多基类,则按照继承列表中的先后顺序)—>成员类构造函数(如果多成员类,则按照类声明中成员变量声明的先后顺序)—>派生类构造函数
析构函数调用顺序则为构造函数调用顺序的逆序
将派生类对象赋给基类对象时,派生类对象将被切除多余的部分以适应基类空间
只有使用指针或引用时,多态才发挥作用
若在类声明中在函数前指定了virtual,则virtual关键字不能再次出现在类声明之外的函数实现中
纯虚函数是这样一种虚拟函数,他只是起到一个占位符的作用,为其子类提供一个可供改写的接口,它本身并不能通过虚拟机制被调用
virtual void ForFutrueUse() = 0;
包含(或继承)一个或多个纯虚函数的类称为抽象类,他不能生成实例
当使用类域操作符显示调用虚拟函数时,该函数已经被静态调用,在编译时刻被静态解析
函数的缺省实参不是在运行时刻决定的,而是在编译时根据调用函数的对象的类型决定的
如果想通过在运行时刻判断根据当时的对象来调用实参,则应该如下实现:
void base::hello(int val = 1)
{
if(val == 1)
val = 1024 // the value you want to be the default
}
void derived::hello(int val = 1)
{
if(val == 1)
val = 2048
}
—-2006/4/13
在c++中可以用0赋给任何任何指针变量,而void*不行,在c中,void*可以,0不行
—-2006/4/15
dynamic_cast 运行时刻转换
void greeting(base * p)
{
Derived * pd;
if(pd = dynamic_cast<Derived *>(p)) // 如果p指向的的确是Derived对象,则转换成功
//….
else // 否则失败,pd = 0
}
void greeting(base &p) // include <type_info>
{
try
{
Derived Dobj = dynamic_cast<Derived &>(p);
}
catch(std::bad_cast)
{…}
}
static_cast 静态转换,作用同c中的强制类型转换 static_cast<int>(value)
const_cast 去除变量的const和voliate性
reinterpret_cast 从底层重新考虑一个变量
Derived Dobj;
string str = reinterpret_cast<string>(Dobj); // actually the result is undefined
typeid(Dobj).name() // the output will be Derived
typeid(Dobj) == typeid(Derived) // true
typeid(Dobj) == typeid(Derived *) // false
class Base
{
virtual Base hello() {}
}
class Derived : public Base
{
Derived hello() {}
}
—-2006/4/16
// 虚拟继承 public virtual Base is also Okay
class Hello : virtual public Base
{
}
在虚拟继承中,中间派生类对虚拟基类构造函数的调用将被自动抑制。虚拟函数构造函数将由最终派生类来调用
虚拟基类的构造函数总是比非虚拟基类的构造函数早些被调用
调用顺序为:按照派生类的继承声明顺序,分别查找每个继承类的继承子树,对于每棵子树采用深度优先进行查找虚拟基类,找到所有虚拟基类并构造之,然后按照继承声明顺序构造非虚拟基类
在虚拟派生下,如果中间派生类改写了虚拟基类的函数,则在最终派生类调用该函数时,中间派生类的特化版本的优先级高于虚拟基类原版本的优先级
私有继承代表了一种has-A的关系,父类的所有protected成员和public成员均被继承为子类的private成员,而公有继承代表了一种is-A的关系
class PeekbackStack : private IntArray
{
public:
// 维持公有访问级别
using IntArray::size;
// …
};
派生类只能将继承得到的成员恢复到原来的访问级别。该访问级别不能比基类中原来指定的级别更严格或更不严格
protected继承将父类所有public成员变为子类的protected成员
—-2006/4/18
断断续续看了几天,终于把要啃得啃完了。主要都是基于对象和面向对象的部分,基础还是要夯实才好。心里踏实。等找到实习单位,应该会可以心定一点了,呵呵
还要考认证,还要做项目,继续啃书去…….
p.s.
1、昨天晚上终于没白熬夜,比赛还蛮好看,暂且不说a米输赢(虽然作为juven的球迷,a米输了对我来说没什么不好的),2队的确打了一场观赏性还可以的比赛。我的评价是,激烈有余,精彩尚可。
2、我有预感,今晚申花能赢,等着瞧吧