学习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. Linux parted 分区

    转自http://tilt.lib.tsinghua.edu.cn/node/889 如何使用parted对齐分区以得到最优性能   Sat, 03/08/2014 - 18:02 - tlblues ...

  2. Spring 事务管理高级应用难点剖析--转

    第 1 部分 http://www.ibm.com/search/csass/search/?q=%E4%BA%8B%E5%8A%A1&sn=dw&lang=zh&cc=CN& ...

  3. ORACLE临时表 转 学习用

    转:http://www.2cto.com/database/201210/163979.html 临时表:像普通表一样,有结构,但是对数据的管理上不一样,临时表存储事务或会话的中间结果集,临时表中保 ...

  4. Swift 性能探索和优化分析

    本文首发在 CSDN<程序员>杂志,订阅地址 http://dingyue.programmer.com.cn/. Apple 在推出 Swift 时就将其冠以先进,安全和高效的新一代编程 ...

  5. Tomcat - 设置 HTTP 基本认证

    在 Tomcat 中设置 HTTP 基本认证的示例 在 $TOMCAT_HOME\conf\tomcat-users.xml 文件中配置角色和用户: <tomcat-users> < ...

  6. ActiveMQ(5.10.0) - Destination-level authorization

    To build upon authentication, consider a use case requiring more fine-grained control over clients t ...

  7. HttpClient(4.3.5) - HttpClient Proxy Configuration

    Even though HttpClient is aware of complex routing scemes and proxy chaining, it supports only simpl ...

  8. Objective-C访问SQLite

    数据库的相关知识我就不去说明了,毕竟只要会sql语言的人就大家都一样. 本案例是在Xcode7.2环境下创建的single view application进行演示操作. 首先第一点,为什么要使用sq ...

  9. Xcode6模拟器时BUG导致键盘无法弹出

    Xcode 6.X版本可能会出现虚拟键盘无法调出,并在控制台出现如下提示:Can't find keyplane that supports type 5 for keyboard iPhone-Po ...

  10. OC5_类别

    // // NSString+Reverse.h // OC5_类别 // // Created by zhangxueming on 15/6/16. // Copyright (c) 2015年 ...