【C++笔记】十、类和对象

1.类定义和成员访问控制

main.cpp

#include <iostream>
#include "Header.h"
using namespace std;

class MyClass1
{
private:
    int mCode = 100;

public:
    string name = "Bill";
    int value = mCode;
};

int main(int argc, const char * argv[]) {
    // 类的定义
    /*
     类:对现实事物的抽象。汽车 : 轮子个数(属性)、载重量(属性)、搭载人数(属性)、最大的时速(属性)....
     
     类的实例化:将抽象具体化。 汽车种类:轿车:轮子个数:4个  载重量:1000kg、搭载人数:5  最大的时速:120km/h
     
     private 只有在内部可以访问
     public  外部内部均可访问
     protected
     */
    
    MyClass1 c1;  // 类的定义,c1的类型就是MyClass1
    
    cout << "c1.name = " << c1.name << endl;   // Bill
    cout << "c1.value = " << c1.value << endl; // 100
    
    MyClass1 *p_c1 = new MyClass1();  // 用指针方式访问类成员
    cout << "p_c1->name = " << p_c1->name << endl;   // Bill
    cout << "p_c1->value = " << p_c1->value << endl; // 100
    delete  p_c1;
    
    MyClass2 c2;  // MyClass2在Header.h里面
    cout << "c2.name = " << c2.name << endl;  // Mike
    cout << "c2.value = " << c2.value << endl;// 300
    return 0;
}

Header.h

#ifndef class_definition_Header_h
#define class_definition_Header_h
#include <iostream>
using namespace std;
class MyClass2
{
private:
    int mCode = 300;
    
public:
    string name = "Mike";
    int value = mCode;
};

#endif

2.定义和实现类中的方法

main.cpp

#include <iostream>
#include "person.h"
using namespace std;

int main(int argc, const char * argv[])
{
    //  实现类中的方法
    Person *p_Person = new Person();
    p_Person->setCode(20);
    p_Person->setName("Bill Gates");
    
    cout << "code = " << p_Person->getCode() << endl;  // 20
    cout << "name = " << p_Person->getName() << endl;  // Bill Gates
    
    delete  p_Person;
    return 0;
}

person.cpp

#include "person.h"

//定义类中的方法
void Person::setCode(int code)  // 类中的方法,setCode方法属于Person,并不是全局的函数
{
    mCode = code;
}

void Person::setName(string name)
{
    mName = name;
}

void Person::setValue(string value)
{
    this->value = value;  // 类的方法的参数名和类的成员变量名相同时,用this指向类的成员变量名
}

int Person::getCode()
{
    return mCode;
}

string Person::getName()
{
    return mName;
}

person.h

#ifndef __implement_method__person__
#define __implement_method__person__
#include <iostream>
using namespace std;

class Person
{
private:
    int mCode;
    string mName;
    string value;
public:
    void setCode(int code);   //  声明原型时可以不指定code,如 void setCode(int)
    void setName(string name);  // 类中的方法
    void setValue(string value);
    int getCode();
    string getName();
};
#endif /* defined(__implement_method__person__) */

3.内联方法

#include <iostream>
using namespace std;
class MyClass
{
public:
    //  内联方法,直接在类的定义中实现方法
    void method()
    {
        cout << "method" << endl;
    }
    
    void process();
};

/*void MyClass::method()  // 这样写方法的话,在main中调用时,是地址的切换
{
    
}*/

inline void MyClass::process()  // 在类的外部实现内联方法
{
    cout << "process" << endl;
}

int main(int argc, const char * argv[]) {
   
    //  内联方法
    MyClass myClass;
    myClass.method();  // 调用内联方法,相当于将代码 cout << "method" << endl; 插入到此处
    myClass.process(); // 同上  cout << "process" << endl;
    return 0;
}

4.类的初始化和构造方法

#include <iostream>
using namespace std;

struct MyStruct
{
    int code;
    string name;
};

class MyClass
{
public:
    int code;
    string name;
    
    MyClass();  // 构造方法,和类名相同
    MyClass(int code, string name);
    MyClass(int code);
    MyClass(string name);
};

MyClass::MyClass()  // 一旦用户自己定义了类的构造方法,C++编译器就不会为类自动创建构造方法,就不能逐个成员的传参,即 MyClass myClass =  {30, "John"}; 会报错
{
    cout << "MyClass" << endl;
}

MyClass::MyClass(int code, string name)
{
    this->code = code;
    this->name = name;
}

MyClass::MyClass(int code)
{
    this->code = code;
    this->name = "null";
    cout << "MyClass(int code)" << endl;
}

MyClass::MyClass(string name)
{
    this->code = 1;
    this->name = name;
    cout << "MyClass::MyClass(string name)" << endl;
}

int main(int argc, const char * argv[])
{
    // 类的初始化和构造方法
    MyStruct myStruct = {20, "Mike"};  // 按顺序传参
    cout << "MyStruct.code = " << myStruct.code << endl; // 20
    cout << "MyStruct.name = " << myStruct.name << endl; // Mike

    //  类的默认域:private,要在外部使用类成员,需要在类中指定public   结构体的默认域:public
    MyClass myClass =  {30, "John"};
    cout << "MyClass.code = " << myClass.code << endl; // 30
    cout << "MyClass.name = " << myClass.name << endl; // John

    MyClass myClass1;  // 打印:MyClass 。用自定义构造方法声明一个变量时,会自动调用该构造方法
    MyClass myClass2 = {40};  // 打印 MyClass(int code)
    MyClass myClass3 = {"Mike"}; // 打印 MyClass::MyClass(string name)

    return 0;
}

5.默认构造方法和参数默认值

#include <iostream>
using namespace std;

class MyClass
{
public:
    void method()
    {
        cout << "method" << endl;
    }
    
    MyClass(int code = 1, string name = "Bill") // 给每个参数默认值,这样在调用构造方法时,即使不传参数,也不会报错
    {
        
    }
    //  按照下式这样写会产生歧义,即在调用没有参数的方法时,系统不知道该使用下式还是使用上式,定义时产生歧义并不会出错,只有在调用时才会出错,即这样写如果不调用无参数的构造方法时编译会通过
   /* MyClass()
    {
        
    }*/
};

int main(int argc, const char * argv[]) {
    // 默认构造方法和参数默认值
    MyClass myClass1;
    MyClass myClass2 = MyClass(20);
    MyClass *p_class = new MyClass(10, "Mike");
    
    return 0;
}

6.析构方法

#include <iostream>
using namespace std;

class Person
{
public:
    string getName()
    {
        return "Bill";
    }
};

class MyClass
{
private:
    Person *p_Person;
    int mCode;
public:
    MyClass(int code)
    {
        p_Person = new Person();
        mCode = code;
        cout << "MyClass构造方法被调用  code = "  << code << endl;
    }

    ~MyClass()  // 析构方法定义,无参数
    {
        delete p_Person;
        cout << "MyClass析构方法被调用 code = " << mCode << endl;
    }

};

int main(int argc, const char * argv[]) {

    MyClass myClass(1); //创建在栈上,系统会自动调用析构方法 打印:MyClass构造方法被调用  code = 1 MyClass析构方法被调用 code = 1
    MyClass *p_c = new MyClass(2); //new创建的空间在堆上 系统bu会自动调用析构方法 打印 MyClass构造方法被调用  code = 2
    delete p_c; // 打印 MyClass析构方法被调用  code = 2
    return 0;
}

7.C++11初始化对象的方式总结

#include <iostream>
using namespace std;

class MyClass
{
public:
    int code;
    string name;

    MyClass()
    {
        
    }

    MyClass(int code, string name)
    {
        
    }

    MyClass(string value1, string value2)
    {
        
    }
};

int main(int argc, const char * argv[]) {
    // C++11初始化对象的方式
    MyClass myClass1 = {20, "Bill"};
    MyClass myClass2{20, "Bill"};  // 在C++11中可以把等号去掉
    
    MyClass myClass3 = {"abc", "bbb"};
    MyClass myClass4 {"abc","bca"};

    return 0;
}

8.常量(const)方法

#include <iostream>
using namespace std;

class MyClass
{
private:
    int mCode = 100;
public:
    int process(int code) const; // const加在后面 
    void method() const
    {
       // mCode = 200;  // method用const修饰后,这句话会报错
    }
};

int MyClass::process(int code) const  // 常量方法要求其内部调用的函数method()也是常量
{
  //  mCode = code;
    method();
    return mCode;
}

int main(int argc, const char * argv[]) {
    // const方法
    // const应该放到方法参数的后面
    MyClass myClass;
    cout << myClass.process(200) << endl;  //  100
    return 0;
}

9.this指针

#include <iostream>
using namespace std;

class MyClass
{
private:
    int code;
    void process(){}
public:
    void method(int code)
    {
        this->code = code;
        (*this).code = code;  // 效果同上

        this->process();
        (*this).process();  // 效果同上
    }
    
    MyClass *getObject()  // 这是一个函数,函数名是getObject,返回值是指针,指向MyClass类型的值,即可以理解为:MyClass* getObject()
    {
        return this;  // 返回this指针,指向MyClass类型的值
    }
};

int main(int argc, const char * argv[])
{
    // this指针
    
    MyClass myClass;
    if(myClass.getObject() == &myClass)
    {
        cout << "equal" << endl;   // equal
    }
        
    return 0;
}

10.对象数组

#include <iostream>
using namespace std;
class MyClass
{
private:
    int mCode;
public:
    MyClass()
    {
        mCode = -1;
    }
    MyClass(int code)
    {
        mCode = code;
    }
    void process()
    {
        cout << mCode << endl;
    }
};
int main(int argc, const char * argv[]) {
    // 对象数组
    MyClass classes[3] = {MyClass(1), MyClass(2)}; // 会自动调用没有参数的构造方法,此时如果类中只定义了有参数的构造方法,那么此句报错
    classes[2].process();  //  打印 -1
    
    MyClass classes1[] = {MyClass(1), MyClass(2)}; 
    
    MyClass *pClasses = new MyClass[3];
    pClasses[1].process();  // 打印 -1 ,因为并没有对数组元素进行单独初始化
    
    MyClass *arrayMyClass[3] = {new MyClass(1), new MyClass(2)}; // 数组的每个元素是指向MyClass的指针
    cout << arrayMyClass[2] << endl; // 打印0x0,没有进行初始化,空指针,此时即便没有定义无参数构造方法,也不会报错
    
    MyClass **ppClasses;
    typedef  MyClass* NewType;
    ppClasses = new NewType[3];  
    for(int i = 0; i<3;i++)
    {
        ppClasses[i] = new MyClass(i + 1);
    }
    ppClasses[2] -> process();  // 打印 3
    return 0;
}

11.类中的常量

#include <iostream>
using namespace std;

class Calendar
{
private:
    const int months = 12; // 这里虽然给了months赋值12,但这只有占位的作用,定义数组时,用months作为数组长度的话,会报错,即便months不用const修饰,也会报错。那怎么不报错呢?有两种方法

    //  方法1,定义枚举类型
    enum{months1 = 12};  // months1和12互为别名
    
    //  方法2  静态常量,存储在全局作用域中,而不是存储在类中
    static const int months2 = 12;
   //  float values[months];  // error,months的值会影响数组尺寸进而影响类所占内存空间时,months必须是一个常量,const定义的是类中的常量,存储在类中,static定义的存储在全局
    float values1[months1];  // 编译时将months1替换为12,此时定义数组不报错
    float values2[months2]; 
public:
    void method()
    {
        cout << months << endl;
    }
};
int main(int argc, const char * argv[]) {
    // 类中的常量
    Calendar calendar;
    calendar.method(); // 打印 12
    return 0;
}

12.类中的枚举类型

#include <iostream>
using namespace std;

class MyClass
{
private:
// 在多个枚举类型中,定义相同的枚举值时,会产生冲突,因为枚举值都是全局的,解决这个冲突的办法就是类美剧
    enum egg{large = 10, medium = 20, small = 30};  // 全局枚举
    enum class shirt:short{large, medium, small};  // 类枚举,short指的是枚举值以short数据类型存储, class可以用struct代替
public:
    void method()
    {
        egg e = large;
        cout << e << endl;
        
        shirt s = shirt::medium;  // 使用::,限定medium为shirt中的枚举值
        
        cout <<  (int)s << endl;        
    }
};

int main(int argc, const char * argv[]) {

    // C++中的枚举类型
    MyClass myClass;
    myClass.method();  // 打印 10  1
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

DUANDAUNNN

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

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

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

打赏作者

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

抵扣说明:

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

余额充值