[类和对象]3 C++面向对象模型初探

?C++编译器如何完成面向对象理论到计算机程序的转化?

[C++编译器是如何管理类、对象、类和对象之间的关系]

通过下面的代码,我们可以的得出:

C++类对象中的成员变量和成员函数是分开存储的

成员变量:

普通成员变量: 存储于对象中,与struct变量有相同的内存布局和字节对齐方式

静态成员变量: 存储于全局数据区



成员函数: 存储于代码段中。

#include "iostream"
#include <cstdio>

using namespace std;

class C1
{
public:
    int i;  //4

    int j;  //4

    int k;  //4 
protected:
private:
}; //12

class C2
{
public:
    int i; //4 存储于对象中
    int j; //4 存储于对象中
    int k; //4 存储于对象中

    static int m; //4 存储于全局数据区
public:
    int getK() const { return k; }   //4 存储于代码段中
    void setK(int val) { k = val; }  //4 存储于代码段中

protected:
private:
}; //12


struct S1
{
    int i;
    int j;
    int k;
}; //

struct S2
{
    int i;
    int j;
    int k;
    static int m;
}; //12

int main(void)
 {
    cout<< sizeof(C1) << endl; //12
    cout<< sizeof(C2) << endl; //12
    cout<< sizeof(S1) << endl; //12
    cout<< sizeof(S2) << endl; //12

return 0;
}

c1:12

c2:12

s1:12

s2:12


?很多对象共用一块代码?代码是如何区分具体对象的?

换句话说: int getK()const{ return k; },代码是如何区分,具体obj1、 obj2、 obj3对象的k值?

面向对象的过程依旧是建立在面向过程的基础上,

比如创建了对象a,在初始化对象a的时候,就调用Tset_ininialize将a的地址[被隐藏封装]变量10传递给函数,

如果调用函数getI()时候(对象a的数值I)时候,实际上仍然传递了对象a的地址

同样的,其他对象也是如此这样做的好处,相比C极大的提高了代码的复用性

[类和对象]3 C++面向对象模型初探

C++普通成员函数都隐式包含一个指向当前对象的this指针,接受调用对象的地址,静态成员函数不包含指向具体对象的指针,因为属于类的,所有对象公有的

[类和对象]3 C++面向对象模型初探


?解释 int getK()const{ return k; },

[类和对象]3 C++面向对象模型初探


全局函数和成员函数的转换

#include <iostream>
using namespace std;

class Test
{
public://成员变量 
    int a;
    int b;

public://构造函数 
    Test(int a = 0, int b = 0) //使用默认参数,就可以[偷懒]使用Test t3,而不加默认参数,则必须写为Test t3(1,2); 
    {
        cout<<"构造函数自动被调用rn"<<endl;
        this->a = a;
        this->b = b;
    }

    Test(const Test& obj)
    {
        cout<<"copy函数自动被调用rn"<<endl;
    }

    ~Test()
    {
        cout<<"析构函数rn"<<endl;
    }

public://成员函数
    void printT()
    {
        cout<<"a:"<<a<<" b: "<<b<<endl;
    }

    //t3 = t1.TestAdd(t2);
    Test TestAdd(Test &t2)
    {
        Test tmp(this->a + t2.a, this->b + t2.b);
        return tmp;
    }

    //t1.TestAdd2(t2); 目的是把 t1 = t1 + t2 
    //返回一个引用 相当于 返回自身 
    //返回t1这个元素 this就是&t1
    Test& TestAdd2(Test &t2)
    {
        this->a = this->a + t2.a;
        this->b = this->b + t2.b;

        return *this; //把 *(&t1) 又回到了 t1元素
    }
};

/*____________把成员函数 转成 全局函数 多了一个参数____________*/

void printT(Test *pT)
{
    cout<<"成员函数 2 全局函数rn"<<endl;    
    cout<<"a:"<<pT->a<<" b: "<<pT->b<<endl;
}


Test TestAdd(Test &t1, Test &t2)
{
    Test tmp;
    tmp.a = t1.a + t2.a;
    tmp.b = t1.b + t1.b;
    cout<<"全局函数  2  成员函数rn"<<endl;
    return tmp;
}
/*________全局函数 转成 成员函数  少了一个参数______________*/


int main(void)
{
    Test t1(1, 2);
    Test t2(3, 4);

    //全局函数方法
//    Test t3;
//    t3 = TestAdd(t1, t2);
//    t3.printT();

    //成员函数方法  //先把测试案例写出来
    {
//        接收匿名对象方法1 
        Test t4 = t1.TestAdd(t2); //匿名对象直接转化成t4
        t4.printT();

        //接收匿名对象方法2
        Test t5;
        t5 = t1.TestAdd(t2); //匿名对象 赋值 给t5
        t5.printT();
    }

    //返回引用
    t1.TestAdd2(t2);
    t1.printT(); 

    return 0;
}

数组类封装

main.cpp

#include <iostream>
#include "MyArray.h"

using namespace std;

int main(int argc, char** argv) {
    Array a1(10);

    for(int i = 0; i < 10; i++) {
        a1.setData(i, i);        
    }
    cout<<"printf a1rn";    
    for(int i = 0; i < a1.length(); i++) {
        cout<< "a1.getData:"<<a1.getData(i) <<endl; 
    }

    cout<<"printf a2rn";    
    Array a2 = a1;
    for(int i = 0; i < a2.length(); i++) {
        cout<< "a2.getData:"<<a2.getData(i) <<endl; 
    }


    cout << "Hello world!n";
    return 0;
}

myarray.cpp

#include "MyArray.h"
//int m_length;
//int *m_space;
Array::Array(int length)
{
    if (length < 0)
    {
        length = 0; //
    }

    m_length = length;
    m_space = new int[m_length];
}

//Array a2 = a1;
Array::Array(const Array& obj)
{
    this->m_length = obj.m_length;
    this->m_space = new int[this->m_length]; //分配内存空间

    for (int i=0; i<m_length; i++) //数组元素复制
    {
        this->m_space[i] = obj.m_space[i];
    }
}

Array::~Array()
{
    if (m_space != NULL)
    {
        delete[] m_space;
        m_space = NULL;
        m_length = -1;
    }
}

//a1.setData(i, i);
void Array::setData(int index, int valude)
{
    m_space[index] = valude;
}

int Array::getData(int index)
{
    return m_space[index];
}

int Array::length()
{
    return m_length;
}

myarray.h

#pragma  once

#include <iostream>
using namespace std;

class Array
{
public:
    Array(int length);
    Array(const Array& obj);
    ~Array();

public:
    void setData(int index, int valude);
    int getData(int index);
    int length();

private:
    int m_length;
    int *m_space;
};

//要求重载以下操作符
// []  ==  !=

原文链接: https://www.cnblogs.com/-Mr-y/p/7804405.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/262876

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月14日 下午3:27
下一篇 2023年2月14日 下午3:27

相关推荐