c++基础知识积累

20161017
1.当一个类A 中没有声明任何成员变量与成员函数,这时sizeof(A)的值是多少?
1
0
4
运行时错误
百度:class CBase
{
};
运行cout<<"sizeof(CBase)="<<sizeof(CBase)<<endl;
sizeof(CBase)=1;
深度探索c++对象模型中是这样说的:     那是被编译器插进去的一个char ,使得这个class的不同实体(object)在内存中配置独一无二的地址。     也就是说这个char是用来标识类的不同对象的。

2指出下面程序哪里可能有问题?
class CBuffer
{
    char * m_pBuffer;
    int m_size;
    public:
        CBuffer()
        {
            m_pBuffer=NULL;
        }
        ~CBuffer()
        {
            Free();
        }
        void Allocte(int size) (1) {
            m_size=size;
            m_pBuffer= new char[size];
    }
    private:
        void Free()
        {
            if(m_pBuffer!=NULL) (2)
            {
                delete[] m_pBuffer;
                m_pBuffer=NULL;
            }
        }
    public:
        void SaveString(const char* pText) const (3)
        {
            strcpy(m_pBuffer, pText); (4)
        }
        char* GetBuffer() const
        {
            return m_pBuffer;
 
    }
 
    };
 
void main (int argc, char* argv[])
{
    CBuffer buffer1;
    buffer1.SaveString("Microsoft");
    printf(buffer1.GetBuffer());
}




1
2
3
4


正确答案应该为: A C D
理由: (1) 分配内存时, 未检测m_pBuffer是否为空, 容易造成内存泄露;
         (3) 常成员函数不应该对数据成员做出修改, 虽然可以修改指针数据成员指向的数据, 但原则上不应该这么做;
         (4) 字符串拷贝时, 未检测是否有足够空间, 可能造成程序崩溃。

以下程序的运行结果是:
1
2
3
4
5
int main( void ){
  int m=5;
  if (m++>5)cout<<m<<endl;
  else cout<<--m;
}

正确答案: B   你的答案: A (错误)

4
5
7
6
m=5,if(m++)>5判断时,++在判断后执行,因此判断为false,之后m自增为6;然后执行cout << --m,自减操作在输出前执行,因此输出5.

类B从类A派生,则类B可以访问类A中的( )成员?

正确答案: A C   你的答案: C D E (错误)

public成员
private成员
protected成员
数据成员
函数成员



x为整型,请用位运算实现x%8  1 。

你的答案 (错误)

1 x&8
参考答案 x&7
x为整型,请用位运算实现x%8  1 。

你的答案 (错误)

1 x&8
参考答案 x&7

请阅读下面代码片段并且回答问题:
1
2
3
4
5
6
7
8
9
10
11
12
#define SIZE_20M (20*1024*1024)
void func_a()
{
     char *temp =  malloc (SIZE_20M)
     return ;
}
void func_b()
{
     char temp[SIZE_20M];
     //...do something using temp
     return ;
}

关于这段代码,下列说法正确的是

正确答案: B   你的答案: D (错误)

func_a 获得临时内存的方式效率通常更高。
func_b 使用了太多的栈,程序可能会在运行时候崩溃。
func_b 存在内存泄露
func_a 和func_b 分配的内存会自动初始化0

//A.栈区效率比堆区高,malloc分配的空间在堆区,临时变量分配在栈区。

区别是:栈区由电脑自己清除(用完自动删),堆区需要程序员清除,或者程序结束后由系统清除

 B.栈一般能放2M大小

 C.func_a会发生内存泄漏(使用动态内存分配,使用完未删除就会造成泄漏。或者是如果没有任何一个指针指向那块动态内存,那它就泄漏了)

 D.堆区和栈区都不会自动初始化,自动初始化会在未赋值的静态/全局区。

void * malloc(usingned int size);单位是(byte)字节数    其作用是在内容的动态存储区分配一个长度位 side 空间,此函数是一个指针型函数,返回的指针是该分配区域的开头的位置(或首地址)  注意指针的类型位void 即不指向任何类型的数据,只提供一个地址。放什么类型的数据,强制转换为什么类型。  如果函数未能成功申请到空间(内存不足),返回空指针 NULL
上面的代码也该改为
1
char *temp = ( char *) malloc (SIZE_20M);

x为整型,请用位运算实现x%8  1 。

你的答案 (错误)

1 x&8
参考答案 x&7
声明一个指向含有10个元素的数组的指针,其中每个元素是一个函数指针,该函数的返回值是int,参数是int*,正确的是()

正确答案: C   你的答案: C (正确)

(int *p[10])(int*)
int [10]*p(int *)
int (*(*p)[10])(int *)
int ((int *)[10])*p
以上选项都不正确
 
首先题目说要声明一个数组指针,  一般我们想到的数组指针是 随便来一个 int(*p)[10],    然后又说每个元素是一个函数指针,那么我们随便来一个 函数指针  int (*pf)(int *) . 然后把(*p)[10]作为一个整体替代 pf     即   int(*(*p)[10]))(int *);    分析: 判断一个复杂式子看最高优先级的,*p是一个指针,然后(*p)外面是[],所以是数组指针, (*p)[10])描述完毕,然后再看外面int(*)(int *)很明显,这是一个函数指针,所以这个数组中每个元素是函数指针

如下程序:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include "stdio.h"
class Base
{
public :
     Base()
     {
         Init();
     }
     virtual void Init()
     {
         printf ( "Base Init\n" );
     }
     void func()
     {
         printf ( "Base func\n" );
     }
};
class Derived:  public Base
{
public :
     virtual void Init()
     {
         printf ( "Derived Init\n" );
     }
     void func()
     {
         printf ( "Derived func\n" );
     }
};
 
int main()
{
     Derived d;
     ((Base *)&d)->func();
     
     return 0;
}
该程序的执行结果
  • Base Init				
    Derived func
  • Base Init
    Base func
  • Derived Init			
    Base func
  • Derived Init
    Derived func

    8个回答

     添加回答
    • 在构造函数不要调用虚函数。在基类构造的时候,虚函数是非虚,不会走到派生类中,既是采用的静态绑定。显然的是:当我们构造一个子类的对象时,先调用基类的构造函数,构造子类中基类部分,子类还没有构造,还没有初始化,如果在基类的构造中调用虚函数,如果可以的话就是调用一个还没有被初始化的对象,那是很危险的,所以C++中是不可以在构造父类对象部分的时候调用子类的虚函数实现。但是不是说你不可以那么写程序,你这么写,编译器也不会报错。只是你如果这么写的话编译器不会给你调用子类的实现,而是还是调用基类的实现。
      在析构函数中也不要调用虚函数。在析构的时候会首先调用子类的析构函数,析构掉对象中的子类部分,然后在调用基类的析构函数析构基类部分,如果在基类的析构函数里面调用虚函数,会导致其调用已经析构了的子类对象里面的函数,这是非常危险的。
      发表于 2015-07-18 21:45:30 回复(1)
    • Derived d;首先创建对象d,找到基类的构造函数Base(){Init();},此时需要调用Init()函数,不要被virtual迷惑,这只是普通的调用函数,虚函数不起作用,所以调用的还是基类的Init(),输出Base Init;
      ((Base *)&d)->func(),虽然是动态联编,但是func()不是虚函数,Base*指针指向派生类不起作用,执行的是基类的func(),输出Base func;

      故选 B
      编辑于 2015-10-05 21:59:05 回复(3)
    • 当派生类对象生成的时候会调用构造函数,首先调用基类的构造函数生成基类部分,然后调用自己的构造函数,析构的时候顺序正好相反,先析构自身的然后析构释放派生类的
      发表于 2015-05-04 09:38:35 回复(0)
    • 要明确一点,在构造函数执行完以后虚函数表才能正确初始化,所以在构造函数中调用虚函数时此时虚函数表还没有被正确初始化,调用的是本类的函数,即静态类型所对应的函数,同理在析构函数中也不能调用虚函数,因为此时虚函数表已经被销毁
      发表于 2016-09-11 12:21:22 回复(0)
    •  ((Base *)&d)->func();,这个不懂,求大神解释.这个按我的理解不就是d->func(),前面的(base*)
      无效,d是派生类对象的,那调用的不就是派生类的函数么。
      发表于 2016-09-13 22:46:14 回复(0)
    • 1.创建派生类对象时,程序首先创建基类对象。基类对象应当在程序进入派生类构造函数之前被创建。
      2. 虚方法:如果没有使用关键字virtual,程序将根据引用类型或者指针类型来选择方法;如果使用了virtual,程序将根据引用或者指针指向的对象的类型来选择方法。
      发表于 2016-07-25 10:37:03 回复(0)
    • 可以看一下
      Effective c++的条款9
      发表于 2016-07-05 15:08:38 回复(0)
    • 1. 子类Derived中并没有定义构造函数,因此在执行Derived d语句的时候会掉用基类中的构造函数,因此输出  Base Init
      2.基类中的void func()函数并没有定义成 virtual void func() = 0;的形式,因此,((Base *)&d)即基类对象的指针所调用的func为基类中的func






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

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

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

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

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

    抵扣说明:

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

    余额充值