欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

mooc程序设计与算法(三)第二周 类和构造函数基础

程序员文章站 2024-03-26 09:10:05
...

注:本系列是 中国大学mooc(慕课) 程序设计与算法(三)C++面向对象程序设计 的课堂笔记和课后习题,每章一次,下面挂上网址:https://www.icourse163.org/course/PKU-1002029030 路漫漫其修远兮,吾将上下而求索(不知道能不能坚持更完系列)……..

一、类成员的可访问范围

  1. 私有成员(private):只能在成员函数内部访问,要访问一定要通过成员函数访问
  2. 公有成员(public):在任何地方都可以访问
  3. 保护成员(protected):以后再说(额。。。。好吧,ppt上是这样写的)
  4. 4.class中,为说明访问范围时,默认为私有,而struct中,默认为公有

二、 成员函数的重载及缺省

  1. 这里注意重载的二义性,比如下面这张图片:

mooc程序设计与算法(三)第二周 类和构造函数基础

三、构造函数

名字与类同名,不能有返回值,可以有参数,作用是初始化对象,如果没写,系统会生成一个默认的无参构造函数,一个类可以有多个构造函数

对象生成时自动调用

四、构造函数在数组中的使用

例子:

#include <iostream>
using namespace std;
class CSample{
    int x;
    public:
        CSample(){
            cout<<"constructor 1 called"<<endl;
        }
        CSample(int n){
            x = n;
            cout<<"constructor 2 called"<<endl;
        }
};
int main()
{
    CSample array1[2];
    cout<<"step1"<<endl;
    CSample array2[2]={4,5};
    cout<<"step2"<<endl;
    CSample array3[2]={3};//注意这里,是一个有参构造函数,一个无参构造函数
    cout<<"steps3"<<endl;
    CSample * array4 = new CSample[
    delete [] aray4;
    return 0;
}

结果:

constructor 1 called
constructor 1 called
step1
constructor 2 called
constructor 2 called
step2
constructor 2 called
constructor 1 called
steps3
constructor 1 called
constructor 1 called

注意下面这个例子,是啥都没有输出的,就是说,这样定义指针数组,是没有调用构造函数的:

#include <iostream>
using namespace std;
class CSample{
    int x;
    public:
        CSample(){
            cout<<"constructor 1 called"<<endl;
        }
        CSample(int n){
            x = n;
            cout<<"constructor 2 called"<<endl;
        }
};
int main()
{
    CSample * array4 ={};
    delete [] array4;
    return 0;
}

复制构造函数

mooc程序设计与算法(三)第二周 类和构造函数基础

复制构造函数起作用的三种情况

  1. 当用一个对象初始化同类的另一个对象时(如:c1、c2是对象,class c1(c2)或者class c1=c2)
  2. 某个函数的参数是该对象,这个函数被调用时
  3. 某个函数的返回值是该对象,则返回函数时,会调用。
    注:赋值语句不会调用复制构造函数(c1=c2),具体的情况看作业题

类型转换构造函数

  1. 目的:实现类型的自动转换
  2. 只有一个参数,而且不是复制构造函数,则看做是类型转换构造函数
  3. 当需要时,系统会调用类型转换构造函数,自动生成一个无名的临时对象。

例子:

#include <iostream>
using namespace std;
class Complex{
    public:
        double real,imag;
        Complex(int i){
            cout<<"i is:"<<i<<" inconstructor call"<<endl;
            real = i;imag=0;
        }
        Complex(double r, double i)
        {
            real = r, imag=i;
        }
};
int main(){
    Complex c1(7,8);
    Complex c2=12;
    c1 = 9;
    cout<<c1.real<<","<<c1.imag<<endl;
    return 0;
}

结果:

i is:12 inconstructor call
i is:9 inconstructor call
9,0

析构函数

1、名字与类同名,前面加“~”,没有参数和返回值,如果不写,则系统会生成缺省的析构函数,关于析构函数什么时候被调用,看下面的例子:

#include <iostream>
using namespace std;
class Demo{
    private:
        int id;
    public:
        Demo(int i){
            id=i;
            cout<<"id="<<id<<" constructed"<<endl;
        }
        ~Demo(){
            cout<<"id="<<id<<" destructed"<<endl;
        }
};
Demo d1(1);
void Func(){
    static Demo d2(2);
    Demo d3(3);
    cout<<"func"<<endl;
}
int main()
{
    Demo d4(4);
    d4 = 6;
    cout<<"main"<<endl;
    {
        Demo d5(5);
    }
    Func();
    cout<<"main ends"<<endl;
    return 0;
}

结果:

id=1 constructed
id=4 constructed
id=6 constructed
id=6 destructed
main
id=5 constructed
id=5 destructed
id=2 constructed
id=3 constructed
func
id=3 destructed
main ends
id=6 destructed
id=2 destructed
id=1 destructed

可以看到,最后的时候,是先析构了静态对象,再析构全局对象

关于复制构造函数,有时候,在dev在调用以对象作为参数的函数的时候,好像没有调用复制构造函数,其实是dev出于优化目的,未生成返回值临时对象而已,vs无此问题。