五:C++基础学习

也许我永远也成为不了强者,但我愿意沿着强者曾经走过的路继续前进。

 

1. 类

语法格式

class   类名称

        {

                定义属性;

                定义方法;

        };

创建类对象的时候,类对象自动包含类的属性和方法。和int,float,bool等一样。int a 表示定义一个整型变量a,那么a具有int具备的属性和方法。

#include <iostream>
#include <string>
#include <vector>

using namespace std;

class Account
{
    // 属性
    string name {"None"};
    double balance {0.0};

    // 方法
    bool deposit(double amount); // 存款
    bool withdraw(double amount); // 取款
};

/*在调用Account类的时候,和int/double/string/bool数据类型是类似的*/

int main()
{
    Account jobs_account;  //创建类的对象
    Account alice_account; //创建类的对象

    Account accounts[] {jobs_account, alice_account}; // 创建类的对象数组

    vector <Account> accounts_vec {jobs_account}; // vector
    accounts_vec.push_back(alice_account);

    Account *p_account = new Account(); // 创建类的指针对象
    delete p_account;

    return 0;
}

类中关键字private/public,

class  类名

        {       private:

                        私有数据和成员函数;

                public:

                        公用数据和成员函数;

        }

private和public被称为成员访问限定符(member access specifier)。用来声明各成员的访问属性。被声明为私有的(private)成员,只能被本类中的成员函数引用,类外不能调用(友元类除外)。被声明为公用的(public)成员,既可以被本类中的成员函数所引用,也可以被类的作用域内的其他函数引用。

如果在类中既不指定private也不指定public,则系统就默认是私有的。

以下定义了类并且在main function中实例化类----类名  对象名;同时在类体内定义了方法函数。

#include <iostream>
#include <string>
#include <vector>

using namespace std;

class Account
{
private:  //只能被本类的方法使用  
    // 属性
    string name {"None"};
    double balance {0.0};

public:   //可以被任何实体访问
    // 方法
    bool deposit(double amount){
        balance += amount;
        cout << name << "刚存入" << amount << "元,现在余额为" << balance << "元" << endl;
        return true;
    }; // 存款
    
    bool withdraw(double amount){
        if (balance >= amount){
            balance -= amount;
            cout << name << "刚取出" << amount << "元,现在余额为" << balance << "元" << endl;
            return true;
        } else {
            cout << name << "余额不足,取款失败" << endl;
            return false;
        }
    }; // 取款
};

int main()
{
    Account jobs_account;
    //不能访问到私有属性或者方法
    // jobs_account.name = "Jobs";
    // jobs_account.balance = 1000.0;

    // cout << jobs_account.name << "现在余额" << jobs_account.balance << "元" << endl;

    jobs_account.deposit(500.0);

    return 0;
}

此外还可以在类体外定义方法函数。此时需要注意到,当成员函数在类体外被定义的时候,必须在函数名前面加上类的名字,予以限定(qualifed),"::"是作用域限定符(field qualifier)或称为作用域运算符,用它声明函数是属于那个类的。

#include <iostream>
#include <string>
#include <vector>

using namespace std;

class Account
{
private:
    // 属性
    string name {"None"};
    double balance {0.0};

public:
    // 方法

    // 设置余额
    void set_balance(double amount){balance = amount;};
    // 获取余额
    double get_balance(){return balance;};

    // 设置姓名
    void set_name(string name);
    // 获取名称
    string get_name();

    // 存款
    bool deposit(double amount);
    // 取款
    bool withdraw(double amount);
};

//可以在类的外面实现函数功能,使用::表达函数的从属关系
void Account::set_name(string name){
    this->name = name; // this指针指向当前对象
}
string Account::get_name(){
    return name;
}
bool Account::deposit(double amount){
    balance += amount;
    cout << name << "刚存入" << amount << "元,现在余额为" << balance << "元" << endl;
    return true;
}
bool Account::withdraw(double amount){
    if (balance >= amount){
        balance -= amount;
        cout << name << "刚取出" << amount << "元,现在余额为" << balance << "元" << endl;
        return true;
    } else {
        cout << name << "余额不足,取款失败" << endl;
        return false;
    }
}

int main()
{
    Account alice_account; //创建类的对象
    alice_account.set_name("Alice's account"); // 设置名称
    alice_account.set_balance(1000.0); // 设置余额

    cout << alice_account.get_name() << "的余额为" << alice_account.get_balance() << "元" << endl;

    alice_account.deposit(200.0);
    alice_account.withdraw(500.0);
    alice_account.withdraw(1500.0);

    return 0;
}

利用构造函数对类和类对象进行初始化

定义的类并不是一个实体,而是一种抽象类型,并不占用存储空间,显然无处容纳数据,如果一个类中的所有成员都是公用的,则可以在定义对象时对数据成员进行初始化。但是,如果数据类型是private或者protected的数据成员,则不能应用上面的方法初始化。

C++提供了构造函数(constructor)来处理对象的初始化。构造函数是一种特殊的成员函数,与其他成员函数不同,不需要用户来调用它,而是在建立对象时自动执行。构造函数是在声明类的时候由设计者定义的,程序用户只需在定义对象的同时指定数据成员的初始值即可。

构造函数的名字必须与类名同名,而不是任意命名。它不具有任何类型,不返回任何值。

#include <iostream>
using namespace std;

class Time                       //声明Time类
{
    public:                      //以下为公用函数
        Time()                   //定义构造成员函数,函数名字和类名相同
        {
            hour = 0;            //利用构造函数对对象中的数据成员赋初值
            minute = 0;
            sec = 0;
        }
        void set_time();         //定义成员函数声明
        void show_time();        //成员函数声明

    private:                     //以下为私有数据
        int hour;
        int minute;
        int sec; 
};

void Time::set_time()           //定义成员函数,向数据成员赋值
{
    cin>>hour;
    cin>>minute;
    cin>> sec;
}
void Time::show_time()          //定义成员函数,输出数据成员的值
{
    cout<<hour<<":"<<minute<<":"<<sec<<endl;
}

int main()
{
    Time t1;                    //建立对象t1,同时调用构造函数t1.Time()
    t1.set_time();              //对t1的数据成员赋值
    t1.show_time();             //显示t1的数据成员的值

    Time t2;                    //建立对象t2,同时调用构造函数t2.Time() 
    t2.show_time();             //显示t2的数据成员的值

    return 0;
}

对上面的程序进行分析:在类中定义了构造函数Time,它和所在的类必须同名,在建立对象时会自动执行构造函数,根据构造函数Time的定义,其作用是对该对象中全部数据成员赋予初始值0。赋值语句是写在构造函数体中的,只有调用构造函数时才执行这些赋值语句。

程序运行时首先建立对象t1,在执行构造函数过程中对t1的数据成员赋予初值0。然后再执行主函数中的t1.set_time()函数。后面正常运行。。。

notes:

(1) 什么时候调用构造函数呢?在建立类对象时会自动调用构造函数。建立类对象时系统自动为该对象分配存储单元,此时执行构造函数,就把指定的初始值送到有关数据成员的存储单元中。每建立一个对象,就调用一次构造函数。

(2) 构造函数没有返回值,因此也没有类型,它的作用只是对对象进行初始化。

(3) 构造函数不需要用户调用,也不能被用户调用。

(4) 如果用户没有定义构造函数,则C++系统会自动生成一个构造函数,只是这个构造函数的函数体是空的,也没有参数,不执行初始化操作。 

带有参数的构造函数

可以采用带有参数的构造函数,在调用不同对象的构造函数时,从外面将不同的数据传递给构造函数,以实现不同的初始化,构造函数的一般形式为

构造函数名(类型1     形参1,类型2     形参2,类型3     形参3,。。。)

由于用户不能直接调用构造函数,因此不能像常规调用函数的方法给处实际参数。实际参数是在定义对象时给出。定义对象的一般形式为

类名    对象名    (实参1,实参2,实参3,。。。)

#include <iostream>
using namespace std;

class Box                              //声明Box类
{
    public:
        Box(int ,int ,int);            //带有参数的构造函数
        int volume();                  //声明计算体积的函数

    private:
        int height;
        int width;
        int length;
};

Box::Box(int h,int w,int len)         //在类外定义带参数的构造函数
{
    height = h;
    width = w;
    length = len;
}

int Box :: volume()
{
    return (height*width*length);
}

int main()
{
    Box box1(12,25,30);               //建立对象box1,并指定box1的长宽高的值 
    cout << "the volume of box1 is "<< box1.volume()<<endl;

    Box box2(15,30,21);
    cout << "the volume of box2 is "<< box2.volume()<<endl;
    return 0;
}

构造函数的重载;

在一个类中可以定义多个构造函数,以便为对象提供不同的初始化的方法,贡用户选用。这些构造函数具有相同的名字,而参数的个数或参数的类型不相同。这称为构造函数的重载

#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Account
{
private:
    // 属性
    std::string name {"account"};
    double balance {0.0};
public:
    void setName(string name){ this->name = name; }; // 设置名称
    // 构造函数
    Account(){
        cout << "没有参数的构造函数被调用" << endl;
    };
    Account(std::string name){
        cout << "带string name的参数函数被调用" << endl;
    };
    Account(double balance){ 
        cout << "带double balan参数的构造函数被调用" << endl;
    };
    Account(string name, double balance){ 
        cout << "带string name和double balance参数的构造函数被调用" << endl;
    };
    // 析构函数
    ~Account(){ 
        cout << name << " 的析构函数被调用" << endl;
    };
};


int main()
{
    {
        Account alice_account;
        alice_account.setName("Alice's account"); // 设置名称
    };
    {
        Account jobs_account;
        jobs_account.setName("Jobs's account"); 

        Account bill_account("Bill's account");
        bill_account.setName("Bill's account"); 

        Account steve_account(1000.0);
        steve_account.setName("Steve's account"); 
    }

    Account *mark_account = new Account("Mark's account", 1000.0);
    mark_account->setName("Mark's account");
    delete mark_account;

    return 0;
}

初始化列表

#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Account
{
private:
    // 属性
    std::string name {"account"};
    double balance {0.0};
public:
    // 打印信息
    void printInfo();
    // 构造函数,初始化参数
    Account(string name, double balance);
   
};

void Account::printInfo(){
    cout << "name: " << name << ", balance: " << balance << endl;
}
// 构造函数内部初始化参数
Account::Account(string name, double balance){
    this->name = name;
    this->balance = balance;
}

int main()
{

    Account *mark_account = new Account("Mark's account", 1000.0);
    mark_account->printInfo(); // 打印信息
    delete mark_account;


    return 0;
}

构造函数初始化列表:

用初始化列表的方式实现对数据成员的初始化。这种方法不是在函数体内对数据成员初始化,而是在函数首部实现的。

语法格式为:

类名 ::构造函数名 (  [ 参数表 ]  ) :成员初始化表  {   }

例如 Box::Box (int h, int w, int len ) : height {h}, width {w} , length {len}   {  }

表示在函数的首部加上一个冒号 ,然后列出参数的初始化列表。把形参h的值初始化数据成员height,把形参w的值初始化数据成员width,把形参len的值初始化数据成员length。后面的花括号是空的,即函数体是空的,没有任何执行语句。

#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Account
{
private:
    // 属性
    std::string name {"account"};
    double balance {0.0};
public:
    // 打印信息
    void printInfo();
    // 构造函数,初始化参数
    Account();
    Account(string name);
    Account(string name, double balance);
   
};

void Account::printInfo(){
    cout << "name: " << name << ", balance: " << balance << endl;
}

// 构造函数内部初始化参数
// Account::Account(){
//     name = "None";
//     balance = 0.0;
// }
// Account ::Account(string name){
//     this->name = name;
//     balance = 0.0;
// }
// Account::Account(string name, double balance){
//     this->name = name;
//     this->balance = balance;
// }

// 构造函数初始化列表
Account::Account()
    :name {"none"}, balance {0.0}{
        
    }
Account::Account(string name)
    :name{name}, balance{0.0}{
        
    }

Account::Account(string name, double balance)
    :name {name}, balance {balance}{
        
    }


int main()
{

    Account alice_account;
    alice_account.printInfo(); // 打印信息

    Account jobs_account {"Jobs's account"};
    jobs_account.printInfo(); 

    Account bill_account {"Bill's account", 1000.0};
    bill_account.printInfo(); 


    return 0;
}

 notes :

(1)如果数据成员是数组,则应当在构造函数的函数体中用语句对其赋值,而不能用参数初始化列表对其初始化。

(2)应该在什么地方指定构造函数的默认参数?应该在声明构造函数的时候指定默认值,而不能只在定义构造函数时指定默认值

析构函数

析构函数也是一个特殊成员的函数,它的作用与构造函数作用相反,它的名字是类名前面加上一个’~‘符号。

当对象生命期结束时,会自动执行析构函数。析构函数的作用不是删除对象,而是在撤销对象占用的内存之前完成一些清理工作,使得这部分内存可以被程序分配给新对象使用。

析构函数不反悔任何值,没有函数类型,也没有函数参数。因此,不能被重载,。一个类中可以有多个构造函数,但是只能有一个析构函数。

析构函数的作用不仅仅可以释放内存,还可以用执行最后一次使用对象之后的所执行的任何操作。

析构函数和构造函数的调用顺序是先构造的后析构,后构造的先析构。

#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Account
{
private:
    // 属性
    std::string name {"account"};
    double balance {0.0};
public:
    void setName(string name){ this->name = name; }; // 设置名称
    // 构造函数
    Account(){
        cout << "没有参数的构造函数被调用" << endl;
    };
    Account(std::string name){
        cout << "带string name的参数函数被调用" << endl;
    };
    Account(double balance){ 
        cout << "带double balan参数的构造函数被调用" << endl;
    };
    Account(string name, double balance){ 
        cout << "带string name和double balance参数的构造函数被调用" << endl;
    };
    // 析构函数
    ~Account(){ 
        cout << name << " 的析构函数被调用" << endl;
    };
};


int main()
{
    {
        Account alice_account;
        alice_account.setName("Alice's account"); // 设置名称
    };
    {
        Account jobs_account;
        jobs_account.setName("Jobs's account"); 

        Account bill_account("Bill's account");
        bill_account.setName("Bill's account"); 

        Account steve_account(1000.0);
        steve_account.setName("Steve's account"); 
    }

    Account *mark_account = new Account("Mark's account", 1000.0);
    mark_account->setName("Mark's account");
    delete mark_account;

    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值