关于初始化C++类成员

在使用C++编程的过程当中,常常需要对类成员进行初始化,通常的方法有两种:

第一种方法:

CMYClass::CSomeClass()
{
  x=0;
  y=1;
}

第二种方法:

CSomeClass::CSomeClass() : x(0), y(1)
{
}

本文将要探讨这两种方法的异同以及如何使用这两种方法。

从技术上说,第二种方法比较好,但是在大多数情况下,两者实际上没有什么区别。第二种语法被称为成员初始化列表,之所以要使用这种语法有两个原因:一个原因是必须这么做,另一个原因是出于效率考虑。

让我们先看一下第一个原因——必要性。设想你有一个类成员,它本身是一个类或者结构,而且只有一个带一个参数的构造函数。

class CMember {
public:
  CMember(int x) { ... }
};

因为CMember有一个显式声明的构造函数,编译器不产生一个缺省构造函数(不带参数),所以没有一个整数就无法创建CMember的一个实例。

CMember* pm = new CMember;    // 出错!!
CMember* pm = new CMember(2);   // OK

如果CMember是另一个类的成员,你怎样初始化它呢?答案是你必须使用成员初始化列表。

class CMyClass {
  CMember m_member;
public:
  CMyClass();
};
// 必须使用初始化列表来初始化成员 m_member
CMyClass::CMyClass() : m_member(2)
{
•••
}

没有其它办法将参数传递给m_member,如果成员是一个常量对象或者引用也是一样。根据C++的规则,常量对象和引用不能被赋值,它们只能被初始化。

使用初始化列表的第二个原因是出于效率考虑,当成员类具有一个缺省的构造函数和一个赋值操作符时。MFC的CString提供了一个完美的例子。假定你有一个类CMyClass具有一个CString类型的成员m_str,你想把它初始化为"Hi,how are you."。你有两种选择:

CMyClass::CMyClass() {
// 使用赋值操作符
// CString::operator=(LPCTSTR);
m_str = _T("Hi,how are you.");
}
// 使用初始化列表
// 和构造函数 CString::CString(LPCTSTR)
CMyClass::CMyClass() : m_str(_T("Hi,how are you."))
{
}

时间: 2024-10-04 11:42:51

关于初始化C++类成员的相关文章

初始化C++类成员和在你的MFC应用中加入位置栏

问题 我的问题是关于初始化C++类成员的.我见过许多这样的代码(包括在你的栏目中也见到过): CSomeClass::CSomeClass() { x=0; y=1; } 而在别的什么地方则写成下面的样子: CSomeClass::CSomeClass() : x(0), y(1) { } 我的一些程序员朋友说第二种方法比较好,但他们都不知道为什么是这样.你能告诉我这两种类成员初始化方法的区别吗? 回答 从技术上说,你的程序员朋友是对的,但是在大多数情况下,两者实际上没有区别.有两个原因使得我们

C#小测试(一):类成员初始化与构造函数执行的顺序

看看下面这段代码,你觉得它会输出什么呢? class Foo { public Foo(string s) { Console.WriteLine("Foo constructor: {0}", s); } public void Bar(){} } class Base { readonly Foo baseFoo = new Foo("Base initializer"); public Base() { Console.WriteLine("Base

java笔记一:类成员的初始化顺序

最近一直在看<thinking in java>一书,感觉里面东西讲的很细,很多东西都没有接触过,是值得各位java程序员仔细品味的一本好书. 今天看了关于类成员初始化那节,以前对于成员初始化顺序没有考虑那么多,没有在意初始化的顺序.今天特意仔细研究了一番. 一个类中,最首先被初始化的是静态成员,也就是有关键字static修饰的成员.只要一个类被使用也就是创建对象或者调用了该类的某个静态方法时静态成员就都会被初始化,并且静态数据在内存中只占用一份存储区域,无论创建多少个对象,静态数据被所有对象

为什么不能在子类的初始化列表里初始化父类的成员

前段时间写了一段代码,其等价形式如下: class A { protected: int n_; }; class B : public A { public: B() : n_(0) {} }; class A { protected :      int n_ ; } ; class B : public A { public :      B ( ) : n_ ( 0 )      { } } ; intellisense会在高亮行提示: "n_" is not a nonsta

谈函数指针(全局/类成员函数)和函数对象

函数指针(全局函数/类成员函数).函数对象(Function object) 一. 函数指针类型为全局函数. #include "stdafx.h"#include <iostream>using namespace std;class TestAction;typedef void (*fp)(int); void Drink(int i){ cout<<"No. "<<i<<" drink..."

一种实现Win32消息处理处理函数的新方法 - 基于Thunk实现的类成员消息处理函数

Windows是一个消息驱动的操作系统,在系统中发生的所有消息均需要通过消息处理过程(或叫窗口过程)进行处理.由于C++给我们在程序设计中带来更多的灵活性(如继承.重载.多态等),所以我们都希望能够使用C++的类来封装Windows中的窗口过程函数,但是Windows规定了窗口过程函数必须定义为一个全局函数,也就是说需要使用面向过程的方法来实现,为了使用面向对象的技术来实现消息处理,我们必须另辟它径.目前我们在网络上见得比较多的方式是使用Thunk将即将传递给窗口过程的第一个参数(HWND hW

C++中static类成员

static局部变量 static局部变量确保不迟于在程序执行流程第一次经过该对象的定义语句时进行初始化 这种对象一旦被创建,在程序结束前不会被撤销.在该函数被多次调用的过程中,静态局部对象会持续存在并保存它的值. #include<iostream> #include<string> #include<assert.h> using namespace std; size_t count_calls() { static size_t ctr=0; return ++

c++-【析构函数写法】如何使用析构函数释放类成员函数申请的堆内存

问题描述 [析构函数写法]如何使用析构函数释放类成员函数申请的堆内存 标题:[析构函数写法]如何使用析构函数释放类成员函数申请的堆内存 环境:win7 64位/AMD CPU/C++ GCC4.7.2/Codeblocks 详细描述:如下所示"代码块1",每次在调用encrypt()函数时均会申请一次内存,如何在析构函数中一次性销毁所有产生的内存,"代码块2"的方法不符合要求 扩展:如果上述问题无较好答案,是否有其他方法可以避免在类函数中使用new,但也能达到目的

抽象类-System.in输入流问题,in类成员属性实例化成为了InputStream

问题描述 System.in输入流问题,in类成员属性实例化成为了InputStream java中在System类中in字段被声明为InputStream类的实例化对象,但是InputStream类为抽象类 应该是无法别实例化的,为什么在System类中被实例化了呢? 解决方案 在System类中是这样定义in的. public final static InputStream in = nullInputStream(); nullInputStream是这样实现的: private sta