class A{
public:
A(int i){
cout<<i<<endl;
}
};
void main(){
void s(int i){
cout<<i<<endl;
}
void s(int i, int j=0){
cout<<i<<endl;
}
void main(){
s(5);
const int i;
i=20;
const int i=100;
const int j=i+100;
long address=(long)&j; //强迫编译器为常量分配存储空间
char buf[j+10];
void main(){
const char c=cin.get();
const char c2=c-'a'+'A';
cout<<c<<" "<<c2<<endl;
}
void main(){
const int i=5;
const int* x; //常量指针
int* const x=&d; //指针常量
int const* x; //常量指针
const int* const x=&d; //常量指针常量
void f(const int i);
class X{
int i;
public:
void modify(){cout<<"haha"<<endl;}
};
const X fun(){return X();}
void main(){
//! fun().modify(); 常量不能为左值,所以下例也不成立:
//! const X g;
//! g.modify();
//!!! 常量一定不能为左值吗?看16题
}
void u(const int* p);
const char* v();
class X{};
X f(){return X();}
void g1(X&){}
void g2(const X&){}
void main(){
//! g1(f()); 临时变量都是常量
g2(f());
}
class Y{
public:
const size;
Y();
};
Y::Y():size(100){}
class X{
enum{i=100};
};
//! class X{
//! const int i;
//! X(){};
//! };
class X{
public:
void f() const{
cout<<"haha..."<<endl;
}
};
void main(){
const X cs;
cs.f();
}
a. #define DEBUG(X) cout<<#X"="<<X<<endl
b. #define TRACE(X) cout<<#X<<endl,X
c. #define FILE(X) char* X##_string
int f(){
return 9;
}
void main(){
char i[]="haha";
DEBUG(i);
for(int j=0;j<5;j++)
TRACE(f());
FILE(one)=i;
cout<<one_string<<endl;
}
class Obj{
char cT;
public:
Obj(char c){
cT=c;
cout<<"Obj::Obj() for"<<c<<endl;
}
~Obj(){
cout<<"Obj::~Obj() for"<<cT<<endl;
}
};
Obj A('A');
void f(){
static Obj B('B');
}
void main(){
cout<<"inside main()"<<endl;
f();
cout<<"leaving main()"<<endl;
}
OUTPUT:
Obj::Obj() forA
inside main()
Obj::Obj() forB
leaving main()
Obj::~Obj() forB
Obj::~Obj() forA
namespace simon{
class A{
public:
void print(){
cout<<"this is simon::A"<<endl;
}
};
char str[]="this is simon::str";
}
void main(){
simon::A v;
v.print();
using namespace simon;
cout<<str<<endl;
}
extern"C" float f(int a, float b);
c++中 f() ===> _f_int_float
c中 f() ===> _f
void main(){
int i(1);
int j(2);
int * const p=&i;
int * pp=(int*)&p;
*pp=(int)&j;
cout<<*p<<endl;
}
const int iii=20;
int & q=iii; //错误,非常量引用不能引用常量
int & qq=20; //错误,非常量引用不能引用常量
const int & qqq=iii; //正确
qqq=23; //错误,常量不能作为左值
引用必须跟一块合法的存储空间联系起来。
a.引用必须被初始化
b. 引用一旦指向一个对象,就不能再指向其它
c. 不能引用NULL ,不能引用常量(除非是常量引用)
void f(int &){}
void g(const int &){}
void main(){
//f(1);
g(1);
}
class X;
void f(X x2);
X x1;
f(x1);
X x2=x1;
class X{
X(X& x) {
cout<<"hehe"<<endl;
}
public:
X(){}
};
void main(){
X xx;
//! X x2=xx;
}
class X;
typedef void (X::*FPT) ();
class X{
public:
int xi;
FPT pp;
X(int j){
xi=j;
pp=X::f;
(this->*pp)();
}
void f(){
cout<<xi<<endl;
}
};
void main(){
X x1(1),x2(2);
FPT p1,p2;
p1=X::f;
p2=x1.f;
(x2.*p1)();
(x2.*p2)();
}
注意,非静态的成员始终要跟this指针结合使用,要用一个对象来使用它而不是一个类型。即使是在类定义内部也要显式用this来强调这种关系。
class X{
public:
X(){}
X(X&){
cout<<"haha..."<<endl;
}
};
void main(){
X x1;
X x2=x1;
x2=x1;
}
foo::foo(int i):base_foo(i){...}
class Z{
public:
Z(int i) {
cout<<"huhu..."<<endl;
}
};
class X{
public:
X(int i) {
cout<<"hehe..."<<endl;
}
};
class Y :public X{
public:
Z z1;
Y(int i):X(i),z1(6) {
cout<<"haha..."<<endl;
}
};
void main(){
Y y(5);
}
试试将上面例子的初始化列表移到函数体内部,会发生什么?
class X{
public:
f(int i,int j) {cout<<"haha"<<endl;}
f(int i){cout<<"haha"<<endl;}
};
class Y:public X{
public:
f(int i){cout<<"hehe"<<endl;}
};
void main(){
Y y;
//! y.f(3,4);
}
class X{
public:
void f(){cout<<"haha"<<endl;}
void ff(){cout<<"hehe"<<endl;}
};
class Y: X{
public:
X::f;
};
void main(){
Y y;
y.f();
//!y.ff();
}
class X{
public:
void foo() {cout<<"X::foo"<<endl;}
};
class Y: public X{
public:
void foo() {cout<<"Y::foo"<<endl;}
};
void bar(X* p){
p->foo();
}
void barbar(X& x){
x.foo();
}
void main(){
Y y;
X* p;
X& m=y;
p=&y;
p->foo();
bar(p);
barbar(m);
}
要想通过p调用Y::foo()该怎么做? 利用virtual 实现多态
45. class no_virtual{
int a;
void f(){};
};
class one_virtual{
int a;
virtual void f(){};
};
class only_virtual{
virtual void f(){};
};
class two_virtual{
virtual void f(){};
virtual void g(){};
};
class null{};
void main(){
cout<< sizeof(no_virtual)
<< sizeof(one_virtual)
<< sizeof(only_virtual)
<< sizeof(two_virtual)
<< sizeof(null)
<<endl;
}
OUTPUT:48441 说明为什么是这个结果?
谈谈在one_virtual 中VPTR与 int a 的位置关系是怎么样的?
Instrument * i;
Brass B;
i = &B;
i->adjust(1);
写出最后一行的汇编代码:
28: Instrument* pi;
29: Brass B;
004010A8 8D 4D F8 lea ecx,[ebp-8]
004010AB E8 73 FF FF FF call @ILT+30(Brass::Brass) (00401023)
30: pi=&B;
004010B0 8D 45 F8 lea eax,[ebp-8]
004010B3 89 45 FC mov dword ptr [ebp-4],eax
31: pi->adjust(1);
004010B6 8B F4 mov esi,esp
004010B8 6A 01 push 1
004010BA 8B 4D FC mov ecx,dword ptr [ebp-4] ;this指针
004010BD 8B 11 mov edx,dword ptr [ecx] ;VPTR指针
004010BF 8B 4D FC mov ecx,dword ptr [ebp-4] ;作参数
004010C2 FF 52 08 call dword ptr [edx+8] ;取虚函数
非静态成员函数的调用都涉及到将this指针传递给函数
class X{
public:
virtual void f()=0 {
cout<<"haha"<<endl;
}
};
class X{
public:
virtual void f(){cout<<"haha"<<endl;}
};
class Y :public X{
public:
virtual void f(){cout<<"hehe"<<endl;}
virtual void ff(){cout<<"hehehehe"<<endl;}
};
void main(){
X* p;
Y y;
p=&y;
Y* py=NULL;
py=static_cast<Y*>(p);
if(py) py->ff();
}
class X{
int xi;
public:
X(int i){xi=i;}
virtual int f() {return xi; }
};
class Y :public X{
int yj;
public:
Y(int i, int j):X(i),yj(j){}
virtual int f() {return X::f()+yj;}
};
void call(X B){cout<<B.f()<<endl;}
void main(){
Y A(5,8);
call(A);
}
OUTPUT:5
类对象在进行值传递时发生了“对象切片”,无论是默认的拷贝构造函数还是手工提供的,编译器都会在其中放一段代码对VPTR进行初始化。这里call的参数类型声明为基类,则调用了基类的拷贝构造函数,将对象的VTPR指向了基类的VTABLE(原本应该指向派生类的VTABLE的)。于是错误发生了。
回忆一下,什么方法可以迫使程序员放弃值传递? 私有拷贝构造函数
class X{
public:
X() {cout<<"X::X()"<<endl;}
X(int i){cout<<"X::X(int)"<<endl;}
};
class Y :public X{
public:
Y(int i){X(5);}
};
void main(){
Y y(6);
}
OUTPUT:X::X()
X::X(int)
class X{
public:
X(int i) {cout<<"X::X(int)"<<endl;}
};
class Y :public X{
public:
};
void main(){
Y y;
}
class Y :public X{
public:
Y(){}
};
为何不能编译通过?如何修改?
class X{
public:
virtual void f(){cout<<"X::f"<<endl;}
X() {f();}
};
class Y : public X{
public:
virtual void f(){cout<<"Y::f"<<endl;}
Y() {f();}
};
class Z : public Y{
public:
virtual void f(){cout<<"Z::f"<<endl;}
Z() {f();}
};
void main(){
Z z;
}
OUTPUT:X::f
Y::f
Z::f
Z的构造函数被调用时,编译器会先调用X的构造函数,然后是Y的,因为构造函数都会将对象的VPTR指向自己类型的VTABLE因此当构造到达X的构造函数体内时,VPTR是指向X的VTABLE的,因此调用的函数就是X版本的函数。
template<class T>
class array{
T aT[100];
public:
array() {for(int i=0;i<100;i++) aT[i]=(T)i;}
T getAt(int index);
};
template<class T>
T array<T>::getAt(int index){return aT[index];}
void main(){
array<double> Darray;
cout<<Darray.getAt(8)<<endl;
}
常量模板:
template<int size=100>
class array{
double aT[size];
public:
array() {for(int i=0;i<size;i++) aT[i]=i;}
double getAt(int index);
};
template<int size>
double array<size>::getAt(int index){return aT[index];}
void main(){
array<10> Darray;
cout<<Darray.getAt(8)<<endl;
array<> Dsarray;
cout<<Dsarray.getAt(99)<<endl;
}
函数模板:
template<class T>
T Tgetmem(T* pT, int index){ return pT[index];}
void main(){
double dd[100];
for(int i=0;i<100; i++) dd[i]=i;
cout<<Tgetmem(dd,5)<<endl;
}
class base{};
class d1: virtual base{};
class d2: virtual base{};
class mi: public d1, public d2{};
typeid,比如S是一个shape* ===> typeid(*S).name()
shape* sp= new circle;
circle* cp= dynamic_cast<circle*>(sp);
if(cp) cout<<”cast successed”<<endl;
class X;
class Y: public X;
X* xp= new Y;
typeid(* xp)==typeid(Y);
typeid(xp) ==typeid(X*);