笔试题集(三)C++ 精选

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、引用
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值