从小白开始学C++ 类与对象二 (this指针和对象数组)

C++对象和类二

主要内容

  1. this指针
  2. 对象数组

this指针

我们在上一次博客中定义了一个Dog类,这里再贴一遍上次的代码
(水一下篇幅)

#include <iostream>
#include <stdio.h>
#include <cstring>
using namespace std;

class Dog //这是一个类的声明
{
private://私有
	char m_name[30];
	int m_age;
	char m_color[20];
public://公有
    Dog();
    Dog(char name[],int age,char color[]);
    ~Dog();
	void howl(int time);
	void running(int time,char location[]);
	void show();
};

Dog :: Dog()
{
    strncpy(m_name, "no_name",30);
    m_age=0;
    strncpy(m_color,"unknown",20);
}

Dog :: ~Dog()
{
    //这是一个析构函数
    cout << "bye! My dear dog, "<<m_name<<"\n";
}

Dog :: Dog(char name[],int age, char color[])
{
    strncpy(m_name, name,30);
    m_age = age;
    strncpy(m_color,color,20);
}

void Dog::howl(int time)
{
    cout << m_name <<" has howled for " << time <<" seconds\n";
}

void Dog::running(int time,char location[])
{
    cout << m_name <<" has ran for "<<time<<" seconds in the "<<location<<"\n";
}

void Dog::show()
{
    cout << "name : " <<m_name<<"\n";
    cout << "age : "<<m_age<<"\n";
    cout << "color : "<<m_color << "\n";
}

int main()
{
    Dog dog1("Peter",2,"white");//隐式调用构造函数
    //显式调用构造函数: Dog dog1 = Dog("Peter",2,"white")
    dog1.show();
    dog1.howl(30);
    char location[30]="playground";
    dog1.running(60,location);
    Dog dog2 = Dog();//注意默认参数无法进行隐式调用
    dog2.show();
    return 0;
}

我们可以看到每个类成员函数都只涉及到一个对象,即调用它的对象
但是如果有的时候方法可能涉及到两个对象
在这种情况下需要使用C++的this指针

我们看这样一个函数:
比较两只Dog类实例对象的年龄,返回年龄较大的那一个
因为是两个对象的比较,所以我们可以在任意一个对象的方法中调用这个compare函数都是可行的

compare函数:

const Dog & Dog::compare(const Dog& s) const
//最后一个const限定this为const,这样将不能使用this来修改对象的值
//前面两个const也是用来防止修改数据
//这里是引用传递
{
    if(s.m_age>m_age)
        return s; 
    else
        return *this;//返回this指针指向的地址
}

上述代码相当于隐式的访问了一个对象(拥有这个方法的对象),显式的访问了另外一个对象,并返回其中一个对象的引用

如果没有this指针,我们在else模块中我们如何返回原本的方法的对象呢?——我们无法称呼这个对象,因为它在函数中并没有实例化,另外一个对象有引用调用的s,而它没有——这里就是this指针发挥作用的时候了

this指针:每个成员函数(保护构造函数和析构函数)都有一个this指针指向调用对象,如果方法需要引用整个对象,则我们使用
(这里打不出来星号)this
(将解除引用操作符*用于指针,就可以得到指针指向的值)

对象数组

用户通常需要创建同一个类的多个对象,所以我们自然想到了数组
对象数组的声明跟其他数组的声明是一样的

Dog mydogs[5];//对象数组的声明

注意这里,如果程序创建为被显式初始化的类对象时,总是调用默认构造函数,所以上述声明将会自动调用隐式默认构造函数

Dog :: Dog()//隐式默认构造函数
{
    strncpy(m_name, "no_name",30);
    m_age=0;
    strncpy(m_color,"unknown",20);
}

当然我们同样可以使用显式构造函数函数来初始化数组元素
必须为每个元素都调用构造函数

具体代码示例:

	const int number = 5;
    Dog mydogs[number]={
    Dog("Mike",3,"black"),//显式构造函数
    Dog(),//隐式默认构造函数
    Dog("Scout",10,"yellow"),
    };

注意这里只初始化了数组中的前三个元素,剩下的两个元素没有声明,那么将使用隐式默认构造函数进行初始化

ps:要创建类对象数组,则这个类必须有默认构造函数

最后完善后的整个代码:

#include <iostream>
#include <cstring>
using namespace std;

class Dog //这是一个类的声明
{
private://私有
	char m_name[30];
	int m_age;
	char m_color[20];
public://公有
    Dog();//默认构造函数
    Dog(char name[],int age,char color[]);//显式构造函数
    ~Dog();//析构函数
	void howl(int time);//具体的成员函数
	void running(int time,char location[]);
	void show();
	const Dog & compare(const Dog&s) const;//使用this指针的函数
};

const Dog & Dog::compare(const Dog& s) const
{
    if(s.m_age>m_age)
        return s;
    else
        return *this;
}

Dog :: Dog()
{
    strncpy(m_name, "no_name",30);
    m_age=0;
    strncpy(m_color,"unknown",20);
}

Dog :: ~Dog()
{
    //这是一个析构函数
    cout << "bye! My dear dog, "<<m_name<<"\n";
}

Dog :: Dog(char name[],int age, char color[])
{
    strncpy(m_name, name,30);
    m_age = age;
    strncpy(m_color,color,20);
}

void Dog::howl(int time)
{
    cout << m_name <<" has howled for " << time <<" seconds\n";
}

void Dog::running(int time,char location[])
{
    cout << m_name <<" has ran for "<<time<<" seconds in the "<<location<<"\n";
}

void Dog::show()
{
    cout << "name : " <<m_name<<"\n";
    cout << "age : "<<m_age<<"\n";
    cout << "color : "<<m_color << "\n";
}

int main()
{
    Dog dog1("Peter",2,"white");//隐式调用构造函数
    //显式调用构造函数: Dog dog1 = Dog("Peter",2,"white")
    dog1.show();
    dog1.howl(30);
    char location[30]="playground";
    dog1.running(60,location);
    Dog dog2 = Dog();//注意默认参数无法进行隐式调用
    dog2.show();
    const int number = 5;//创建对象数组
    Dog mydogs[number]={
    Dog("Mike",3,"black"),
    Dog(),
    Dog("Scout",10,"yellow"),
    };
    Dog top = mydogs[0];//创建一个类对象
    for(int i=1;i<number;i++)//循环比较
        top = top.compare(mydogs[i]);
    cout << "\n My oldest dog's information:\n";//输出结果
    top.show();
    return 0;
}

输出结果:

name : Peter
age : 2
color : white
Peter has howled for 30 seconds
Peter has ran for 60 seconds in the playground
name : no_name
age : 0
color : unknown

 My oldest dog's information://这里输出了比较后的信息
name : Scout
age : 10
color : yellow
bye! My dear dog, Scout//这里有两个scout是因为Dog top最后是它的引用变量
bye! My dear dog, no_name
bye! My dear dog, no_name
bye! My dear dog, Scout
bye! My dear dog, no_name
bye! My dear dog, Mike
bye! My dear dog, no_name
bye! My dear dog, Peter
//一共创建了八个实例,程序结束时都会自动调用析构函数进行清理

下一篇预告:操作符重载、友元函数

码字不易,点个赞吧

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

国家一级假勤奋研究牲

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值