1、 求解下列代码的打印值
#include <iostream>
class A
{
public:
A(){}
virtual void doSth(){std::cout<<"This is A "<<std::endl;};
void donull(void)
{
std::cout<<"This is donull function "<<std::endl;;
}
};
int main(void)
{
A *d = NULL;
d->donull();
((A*)0)->donull();
((A*)NULL)->donull();
return 0;
}
/*
//打印如下:
This is donull function
This is donull function
This is donull function
//
1)如果某个方法没有使用任何成员变量,不需要this指针,不需要动态绑定(一般来说非virtual方法),则使用null就能激活
2)如果某个方法仅仅 使用了 静态成员变量,也是可以的,如 如下题目3, main函数如下使用
A *pa=NULL;
pa->print1("this");
如果使用了其他成员变量,会产生未知错误,如:Segmentation fault (core dumped)
*/
2、写出打印结果并解释
#include <iostream>
class A
{
public:
A(){doSth();}
virtual void doSth(){std::cout<<"This is A "<<std::endl;};
void doOthers(class A& a)
{
a.doSth();
}
};
class B:public A
{
public:
virtual void doSth(){std::cout<<"This is B "<<std::endl;};
void doSthInB()
{
doOthers(*this);
}
};
int main(void)
{
B b;
A *a = &b;
a->doSth();
b.doSthInB();
return 0;
}
/*
print result:
This is A
This is B
This is B
*/
3、写出打印结果(关于 实参传递类参数、返回类实参、拷贝构造(默认,重写)、静态成员 计数器)
#include <iostream>
class A
{
static int count;
public:
A(){count++; std::cout<<"A() " << count << std::endl;}
//A(const A &a){count++; std::cout<<"A(const A &) " << count << std::endl;}
static void print(const char* msg = 0)
{
if(msg)
{
std::cout << msg << ":";
}
std::cout << "Obj count = " << count << std::endl;
}
~A(){std::cout<<"~A " << count <<std::endl; count--;};
};
int A::count = 0;
A fun(A x) // #☆_☆#传参的时候 如果没有重写默认拷贝构造函数,则不会调用默认的构造函数,而是直接内存拷贝
{
x.print("fun print");
return x; //return 时候会创建一个临时对象,也要调用拷贝构造函数,如果没有重写拷贝构造函数,则直接内存拷贝,不调用默认构造函数
//如果 直接调用 fun(a), 则return创建的临时对象,析构函数会在 fun 执行完了调用析构
//如果 直接调用 A a1 = fun(a), 则return创建的临时对象,析构函数会在 a1 生命周期结束的时候被调用
}
int main(void)
{
A a;
A::print("after construction of a ...");
A a1 = fun(a); // 形式上是和 A a1(p); p 是 fun 的return值,一样的,需要调用拷贝构造函数
A::print("after construction of a1 ...");
return 0;
}
/*
print result:
A() 1
after construction of a ...:Obj count = 1
A(const A &) 2
fun print:Obj count = 2
A(const A &) 3
~A 3
after construction of a1 ...:Obj count = 2
~A 2
~A 1
*/
/*
如果 删除掉覆盖默认构造函数的拷贝构造函数
A(const A &a){count++; std::cout<<"A(const A &) " << count << std::endl;}
打印结果如下:
A() 1
after construction of a ...:Obj count = 1
fun print:Obj count = 1
~A 1
after construction of a1 ...:Obj count = 0
~A 0
~A -1
==>虽然默认拷贝构造函数未被调用,但是 析构函数 还是会被调用的
*/
4、string 对象 常量属性
#include <iostream>
#include <string>
std::string foo(void)
{
std::string s = "123456"; //每次调用都会新创建一个新的string 对象
std::cout << "foo s addr = " << &s << std::endl;
return s;
}
std::string foo1(void)
{
std::string s = foo(); //这个对象地址同foo 函数里的对象的地址
std::cout << "foo1 s addr = " << &s << std::endl;
return s;
}
void bar(const std::string &str)
{
std::cout << " str addr = " << &str << std::endl << std::endl;
}
int main(void)
{
bar("123456");
std::string a1= foo();
std::cout << " a1 addr = " << &a1 << std::endl << std::endl;
std::string a2= foo1();
std::cout << " a2 addr = " << &a2 << std::endl << std::endl;
std::string a4 = "1234556";
std::string a5 = "1234556";
std::cout << " a4 addr = " << &a4 << std::endl;
std::cout << " a5 addr = " << &a5 << std::endl;
return 0;
}
/*
print result:
str addr = 0x7ffc1521a620
foo s addr = 0x7ffc1521a5c0
a1 addr = 0x7ffc1521a5c0
foo s addr = 0x7ffc1521a5e0
foo1 s addr = 0x7ffc1521a5e0
a2 addr = 0x7ffc1521a5e0
a4 addr = 0x7ffc1521a600
a5 addr = 0x7ffc1521a620
*/
5、关于静态成员的 初始化,继承
#include <iostream>
class A
{
public:
A():val(1){};
int val;
//private: //如果打开的话,dat 成员将不能被子类继承
static int dat;
};
int A::dat = 1;
class B : public A
{
public:
B():val(2){};
int val; // 子类会覆盖父类的同名成员变量
};
//int B::dat = 2; // 如果加上这个,gcc会报错,提示 已经有定义过了(int A::dat = 1;), 这里就不能再重复定义了
int main(void)
{
//如下所有的修改,都是修改同一个值
B::dat = 2;
A::dat = 3;
A c;
c.dat = 4;
B d;
d.dat = 5;
return 0;
}
6、引用的多态性
#include <iostream>
#include <string>
class A
{
public:
virtual void fun1(void);
virtual void fun2(void);
};
class B : public A
{
public:
void fun1(void);
void fun4(void);
};
void A::fun1(void){ std::cout << " A " << __FUNCTION__ << std::endl;}
void A::fun2(void){ std::cout << " A " << __FUNCTION__ << std::endl;}
void B::fun1(void){ std::cout << " B " << __FUNCTION__ << std::endl;}
void B::fun4(void){ std::cout << " B " << __FUNCTION__ << std::endl;}
int main(void)
{
B b;
A &a = b;
a.fun1(); // 多态性 指向 B的fun1
a.fun2(); // 报错
return 0;
}
7、引用
// case 1
int s = 1;
const int &ps = s;
ps = 5; //error
s = 5; //ok
//case 2
const int s = 1;
int &ps = s; // error
8、union
#include <iostream>
#include <string>
#include <cstring>
typedef union TEST{
int i;
char a[5];
} test_t;
int main(void)
{
test_t t={0};
t.a[0] = 0xf;
t.a[1] = 0xd;
t.a[2] = 0xc;
t.a[3] = 0xb;
t.a[4] = 0xa;
std::cout << std::hex <<" t.i="<< t.i << std::endl;
std::cout << std::hex << " t.a[0]=0x" <<(int)t.a[0] << ", t.a[1]=0x" <<(int)t.a[1] << std::endl;
return 0;
}
/*
position order in memery
---------------------------------
char a[5] |a[4]|a[3]|a[2]|a[1]|a[0]|
char a[5] | 0xa| 0xb| 0xc| 0xd| 0xf|
int i |0xf|0xd|0xc|0xb|0xa|
---------------------------------
t.i=b0c0d0f
t.a[0]=0xf, t.a[1]=0xd
*/
9、delete new 析构执行时机
#include <iostream>
#include <string>
class A
{
public:
A(){dat++; std::cout<<"A() " << dat <<std::endl;}
~A(){std::cout<<"~A() " << dat <<std::endl;dat--;}
static int dat;
};
int A::dat = 0;
int main(void)
{
{
A a[2];
//delete[] a; //error delete 释放 new 出来的对象
//delete &a[1]; //error
//delete &a[0]; //error
}
//a[0].dat = 3; //加上上面的{}后,这么调用会报错,超出作用域了,而且在括号(})结束的地方就会调用析构函数,
A *b = new A[2];
std::cout << " A " << __FUNCTION__ << std::endl;
delete[] b;
std::cout << " B " << __FUNCTION__ << std::endl;
return 0;
}
/* print info
A() 1
A() 2
~A() 2
~A() 1
A() 1
A() 2
A main
~A() 2
~A() 1
B main
*/
10、基类 析构函数要定义成虚函数,防止派生类的析构函数用不上,会造成资源的泄漏
#include <iostream>
using namespace std;
class A{
public:
A() {cout << "construct A" << endl;};
virtual ~A() {cout << "destructor A!" << endl;}; // 1
virtual void DoSomething() {cout << "Do something in A!" << endl;};
};
class B : public A{
public:
B() {cout << "construct B" << endl;};
virtual ~B() {cout << "destructor B!" << endl;};
virtual void DoSomething() {cout << "Do something in B!" << endl;};
};
int main(void){
A *p = new B;
//当基类是虚函数时,基类的指针将表现为派生类的行为(非虚函数将表现为基类行为)
p->DoSomething();
delete p;
return 0;
}
/*
construct A
construct B
Do something in B!
destructor B!
destructor A!
//如果把 1 位置析构函数的 virtual 去掉, 打印如下
construct A
construct B
Do something in B!
destructor A!
*/
11、引用
12、引用