[类和对象]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极大的提高了代码的复用性
C++普通成员函数都隐式包含一个指向当前对象的this指针,接受调用对象的地址, 静态成员函数不包含指向具体对象的指针,因为属于类的,所有对象公有的
?解释 int getK() const { return k; },
全局函数和成员函数的转换
#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<<"构造函数自动被调用\r\n"<<endl; this->a = a; this->b = b; } Test(const Test& obj) { cout<<"copy函数自动被调用\r\n"<<endl; } ~Test() { cout<<"析构函数\r\n"<<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 全局函数\r\n"<<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 成员函数\r\n"<<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 a1\r\n"; for(int i = 0; i < a1.length(); i++) { cout<< "a1.getData:"<<a1.getData(i) <<endl; } cout<<"printf a2\r\n"; 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; }; //要求重载以下操作符 // [] == !=