码迷,mamicode.com
首页 > 编程语言 > 详细

C++编码练习后知识小结

时间:2015-04-11 23:46:57      阅读:145      评论:0      收藏:0      [点我收藏+]

标签:

头一次记录技术相关知识,相信将来一定能看到自己的进步!

最近忙着找工作,因为要应对各种笔试。所以做了几个练习,不练不知道一练吓一跳。

发现自己对C++的基础知识几乎忘光了。突然感慨自己复制粘贴好多年的结果。。。

 

1.关于构造和析构顺序:

include "stdafx.h"

#include <iostream>

using namespace std;

class One

{

public:

            One(){cout<<"One ";}

            ~One(){cout<<"~One ";}

};

 

class Two

{

public:

             Two(int j){cout<<" Two ";}

            ~ Two(){cout<<"~ Two ";}

};

 

class Three

{

public:

            Three(){cout<<"Three ";}

            virtual ~Three(){cout<<"~Three ";}

};

 

class Four : public Three

{

public:

            Four (int j)

            {

                   cout<<"Four  ";

                   pb = new Two(j);

            }

            ~Four ()

            {

                   delete pb;

                   cout<<"~Four ";

            }

 

private:

            Two *pb;

            One a;

};

int _tmain(int argc, _TCHAR* argv[])

{

            Three* pc = new Four(1);

            delete pc;

 

            return 0;

}

Three One Four Two ~Two ~Four ~One ~Three

这个例子主要是说基类虚析构函数的作用。

从答案可以看出来,构造的顺序是基类,子类的成员对象,子类。

如果没有 pb = new Two(j)这句,只有Two *pb;则根本不会调用Two 的构造函数(突然觉得自己很傻,这根本就是显然是的事却犹豫了一下。。。)

如果class Three没有声明虚析构函数的话,则调用Delete pc语句的时候,不会调用其他的析构函数。

同样如果_tmain函数中的语句改为 Four* pc = new Four(1)

此时class three中是否为虚析构函数就无所谓了,delete时会按顺序调用其他类的析构函数。

 

总结一下,基类中的虚析构函数主要是用于防范上转型对象上(自己这么觉得)。

delete上转型对象时,如果此时基类的析构函数是虚函数,则顺序调用子类对象关联的其他类的析构函数。

如果此时基类的析构函数不是虚函数,则只调用基类的析构函数,这就为内存泄漏留下了隐患。

 

2.  关于Sizeof:

#include <iostream>

class A

{

public:

     A(){}

     A(int a,unsigned int b):m_a(a),m_b(b),m_c(){}

public:

     int m_a;

     unsigned int m_b;

     A* m_c;

};

 

class B : public A

{

public:

       B(){}

public:

       static int m_d;

};

 

int _tmain(int argc, _TCHAR* argv[])

{

       A* a;

       B b;

       std::cout<<sizeof(A)<<" ";

       std::cout<<sizeof(b)<<" ";

       std::cout<<sizeof(a)<<" ";

       a = new B[2];

       std::cout<<sizeof(a)<<" ";

       return 0;

}

答案是12 12 4 4    

一直以为unsigned int 的大小是2,今天试了一下原来是4。

再者因为a是指针所以a指向的所有东西sizeof都是4。不要被a = new B[2]所迷惑。

那天也遇到一个类似的问题,如果单纯的一个空类什么变量也没有,这个空类的sizeof是1(具体为什么是1还没搞清楚。~~老中医的Style,拿来就用嘛)

再者如果类中有静态参数,静态参数是不占空间的,估计是因为静态参数的存储不再类内的原因。初始化也不再类内。

 

3. 还是构造函数

#include <iostream>

class A

{

public:

A(int n=0):m_i(n){std::cout<<m_i;}

protected:

     int m_i;

};

 

class B : public A

{

public:

       B(int n):m_j(n),m_a(--m_j),m_b(){std::cout<<m_j;}

private:

     int m_j;

       A m_a;

       A m_b;

       static A m_c; 

};

 

int _tmain(int argc, _TCHAR* argv[])

{

     B b(2);

     std::cout<<std::endl;

     return 0;

}

 

 答案是0101        

这道题很诡异也是很好的一道题,一开始觉得答案肯定错了,一运行答案真的没错。。。

这道题主要是考察类的构造顺序和成员变量的初始化顺序。

第一个输出0是因为首先调用基类的构造函数,基类中默认参数是0。

第二个输出1是因为执行A m_a;时调用了A的构造函数,

由B的初始化列表B(int n):m_j(n),m_a(--m_j)可以看出首先对m_j赋值为2,

接着m_a(--m_j)将1传给A的构造函数所以输出1.

第三个输出0是因为A m_b;调用a的构造函数时没有传入参数,所以使用默认参数0.

第四个输出1是因为最后要调用B的构造函数,虽然传入的是2,但是之前的--m_j使m_j的值变成了1。

 

C++编码练习后知识小结

标签:

原文地址:http://www.cnblogs.com/JerryloveAda/p/4412854.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!