学习C++类,首先要说C中的结构体,虽然C++类扩展了C中的结构体,可以添加成员函数,但他们是有区别的。在结构体中,成员变量、成员函数都是公有的,而类中,一般是成员变量是私有的,成员函数是公有的,私有的成员变量一般对象不可调用(数据隐藏),只能是成员函数来调用。

代码1:

 #include <iostream>
using namespace std; class MyClass
{
private:
int m_value;
public:
int get();
void set(int n);
}; int MyClass::get()
{
return m_value;
} void MyClass::set(int n)
{
m_value=n;
} int main()
{
MyClass myclass;
//cout<<myclass.m_value<<endl;
cout<<myclass.get()<<endl; myclass.set();
cout<<myclass.get()<<endl;
return ;
}

如果没有注释掉26行,编译时会出现error C2248: 'm_value' : cannot access private member declared in class 'MyClass',即应证了类中的私有成员变量只能通过公有成员函数调用,对象是不能直接获取的。

执行27行后,显示的是一个不确定的负数,其实,执行25行的MyClass myclass;后编译系统为对象myclass的数据成员(m_value)分配内存空间,并调用默认构造函数MyClass( )自动地初始化对象myclass的m_value值设置为一不确定的值。当然,我们也可以自己设计构造函数。

构造函数主要可以分为如下几种形式:

无参数构造函数 如果创建一个类你没有写任何构造函数,则系统会自动生成默认的无参构造函数,函数为空,什么都不做。只要你写了一个下面的某一种构造函数,系统就不会再自动生成这样一个默认的构造函数,如果希望有一个这样的无参构造函数,则需要自己显示地写出来;

一般构造函数(也称重载构造函数) 一般构造函数可以有各种参数形式,一个类可以有多个一般构造函数,前提是参数的个数或者类型不同(基于c++的重载函数原理)。 创建对象时根据传入的参数不同调用不同的构造函数;

复制构造函数(也称为拷贝构造函数) 复制构造函数参数为类对象本身的引用,用于根据一个已存在的对象复制出一个新的该类的对象,一般在函数中会将已存在对象的数据成员的值复制一份到新创建的对象中.若没有显示的写复制构造函数,则系统会默认创建一个复制构造函数,但当类中有指针成员时,由系统默认创建该复制构造函数会存在风险,具体原因请查询 有关 “浅拷贝” 、“深拷贝”的文章论述.

代码2

 #include <iostream>
using namespace std; class MyClass
{
private:
int m_value;
public:
MyClass(){m_value=;} //无参构造函数
MyClass(int n){m_value=n;} //一般构造函数
MyClass(const MyClass &my){m_value=my.m_value;} //复制构造函数
int get();
void set(int n); }; int MyClass::get()
{
return m_value;
} void MyClass::set(int n)
{
m_value=n;
} int main()
{
MyClass myclass1;
cout<<myclass1.get()<<endl; MyClass myclass2();
//MyClass myclass2=MyClass(4);
cout<<myclass2.get()<<endl; MyClass myclass;
MyClass myclass3(myclass);
cout<<myclass3.get()<<endl; return ;
}

代码2分别定义了无参构造函数、一般构造函数和复制构造函数。在主函数中,29行调用了无参构造函数,32行调用了一般构造函数,且它的作用等价注释掉的33行,37行调用了复制构造函数,即通过对象myclass来创建对象myclass3。

其实对于无参构造函数、一般构造函数还有另一种形式:

queue(int qs):qsize(qs),items(0),front(NULL),rear(NULL){}

即由冒号和逗号分隔的初始化列表,被放在构造函数参数的右括号后,函数体的左括号之前。

代码3

 #include <iostream>
using namespace std; class MyClass
{
private:
int m_value;
public:
MyClass(int n){m_value=n;}
int get();
void set(int n);
void show();
}; int MyClass::get()
{
return m_value;
} void MyClass::set(int n)
{
m_value=n;
} void MyClass::show()
{
cout<<m_value<<endl;
} int main()
{
MyClass myclass1();
myclass1.show(); MyClass myclass2=myclass1;
myclass2.show(); return ;
}

在代码3中,32行调用自定义的构造函数创建对象myclass1,而35行,却是调用的系统默认的复制构造函数,即系统为对象myclass2 分配了内存并完成了与对象myclass1 的复制过程.编译系统的机制是,如果系统类没有自己定义复制构造函数,会采用默认的,如果自己定义了,则会用定义的,其实代码3和代码4(自定义)的作用和效果是相同的。

代码4

 #include <iostream>
using namespace std; class MyClass
{
private:
int m_value;
public:
MyClass(int n){m_value=n;}
MyClass(const MyClass &my){m_value=my.m_value;}
int get();
void set(int n);
void show();
}; int MyClass::get()
{
return m_value;
} void MyClass::set(int n)
{
m_value=n;
} void MyClass::show()
{
cout<<m_value<<endl;
} int main()
{
MyClass myclass1();
myclass1.show(); MyClass myclass2=myclass1;
myclass2.show(); return ;
}

代码4中10行就是我们自定义的复制构造函数,复制构造函数是一种特殊的构造函数,函数的名称必须和类名称一致,它必须的一个参数是本类型的一个引用变量,且没有其他参数或其他参数都有默认值。

复制构造函数用于将一个对象复制到新创建的对象中,也就是说,它用于初始化过程中(包括按值传递参数),而不是常规的赋值过程中。
那么什么时候需要一般的构造函数,什么时候需要复制构造函数:总的来说,以下三种情况需要复制构造函数,具体

1. 对象以值传递的方式传入函数参数

2. 对象以值传递的方式从函数返回

3. 对象需要通过另外一个对象进行初始化

其实以上代码中的复制构造函数就是所谓的浅拷贝,即只对对象中的数据成员进行简单的赋值,默认拷贝构造函数执行的也是浅拷贝。大多情况下“浅拷贝”已经能很好地工作了,但是一旦对象存在了动态成员或静态成员,那么浅拷贝就会出问题。

再次学习C++类之构造函数的更多相关文章

  1. 再次学习 java 类的编译

    做JAVA开发的都知道myeclipse, 我们在myeclipse中新建一个类,然后保存, 如何正常的话,那么在项目指定的目录(也就是项目的output目录)就会生成同名的class文件, 可是,我 ...

  2. 【C++学习之路】派生类的构造函数(一)

    一.简单派生类的构造函数 1.所谓简单派生类,就是指派生类中不包含基类的内嵌对象的派生类. 2.一般来说,这样的派生类的构造函数的形式是: student( int i, string nam, in ...

  3. C++学习17派生类的构造函数

    基类的构造函数不能被继承,在声明派生类时,对继承过来的成员变量的初始化工作也要由派生类的构造函数来完成.所以在设计派生类的构造函数时,不仅要考虑派生类新增的成员变量,还要考虑基类的成员变量,要让它们都 ...

  4. 【C++学习之路】组合类的构造函数

    1 #include <iostream> using namespace std; class A { public: A(){ cout << "调用A无参&qu ...

  5. 【C++学习之路】派生类的构造函数(三)

    三.多层继承的派生类 1.多层继承的派生类只需在构造函数的初始化列表中写出直接基类的构造函数即可 class student { public: student(int n, string nam) ...

  6. 【C++学习之路】派生类的构造函数(二)

    二.有内嵌对象的派生类 1.一般来说,我们会这样定义构造函数 student( int i, string nam, int pid, string pnam, int sid) : person( ...

  7. C++学习之路—继承与派生(二):派生类的构造函数与析构函数

    (根据<C++程序设计>(谭浩强)整理,整理者:华科小涛,@http://www.cnblogs.com/hust-ghtao转载请注明) 由于基类的构造函数和析构函数是不能被继承的,所以 ...

  8. C++学习笔记(6)----基类和派生类的构造函数和析构函数的执行顺序

    基类和派生类:构造函数和析构函数的执行顺序 在Visual Studio中,新建控制台工程,构造类如下: #include<iostream> using namespace std; c ...

  9. c++学习笔记4,派生类的构造函数与析构函数的调用顺序(一)

    測试源代码: //測试派生类的构造函数的调用顺序何时调用 //Fedora20 gcc version=4.8.2 #include <iostream> using namespace ...

随机推荐

  1. BeanDefinitionRegistry extends AliasRegistry

    // 用该Registry注册一个新定义的bean,但是新的bean必须支持父的定义和子的定义void registerBeanDefinition(String beanName, BeanDefi ...

  2. 使用cocos2d-x制作 Texture unpacker

    使用cocos2d-x制作 Texture unpacker 没错,就是unpacker. 在大多数游戏包里面,可以找到很多纹理图集,他们基本上是用texture packer制作的,有plist文件 ...

  3. Recovery启动流程(2)---UI界面

    转载请注明来源:cuixiaolei的技术博客 Recovery启动流程系列文章把recvoery目录下文件分成小块讲解,最后再以一条主线贯穿所有的内容.这篇文章主要讲解Recovery-UI的相关内 ...

  4. Windows 平台下Git 服务器搭建

    由于项目中一直在使用git作为版本管理,自己对git的理解.使用都还不是怎么的熟悉,所以准备深入了解一下git及一些常用命令的使用,于是干脆把服务端架上,通过自己的PC作为服务端同时作为客户端的角色进 ...

  5. JDBC的批量批量插入

    本文部分转载于:http://blog.itpub.net/29254281/viewspace-1151785/ http://www.cnblogs.com/chenjianjx/archive/ ...

  6. poj 3254 状态压缩DP

    思路:把每行的数当做是一个二进制串,0不变,1变或不变,找出所有的合法二进制形式表示的整数,即相邻不同为1,那么第i-1行与第i行的状态转移方程为dp[i][j]+=dp[i-1][k]: 这个方程得 ...

  7. loadrunner做webservice接口之简单调用

    今天听大神讲了webservice做接口,我按照他大概讲的意思自己模拟实战了下,可能还有很多不对,一般使用webservice做接口,会使用到soapui,但是用了loadrunner以后发现lr很快 ...

  8. 解决python 提示 SyntaxError: Missing parentheses in call to 'print'

    刚刚学习python,练习他的输出,发现输出一个常量时报错了,如下: 发现是因为python2.X版本与python3.X版本输出方式不同造成的在python3.X的,输入内容时都要带上括号pytho ...

  9. SQL Server2008新特性Filesteam的使用

    Filesteam是SQL Server2008的新特性,它结合了SQL Server和NTFS文件系统,为Blob类型的数据提供了比较高效的存储和访问方案.我们最近的一个项目就是采用SQL Serv ...

  10. 学习IT技术的技巧

    怎样学习一个知识A? (1).为什么需要A?  (*) (2).什么是A?  (*) (3).怎么使用A[最简答的]?  (*) (4).使用A时注意的问题?  (*) (5).A的应用领域. (6) ...