类:
类是一种将抽象转化为用户定义类型(用户定义类型:实现抽象接口的类设计)的C++工具。
接口:
接口是一个共享框架是一个共享框架,共两个系统(eg:我与计算机)交互时使用。比如我们使用计算机时,程序接口将我们的意图转化为存储在计算机中的具体信息。
通常,将接口(类定义)放在头文件(类声明)中,将实现(类方法的代码)放在源代码文件中。
一般,我们将类名首字母大写(常见但不通用的约定)
类设计:
类设计应尽可能将公有接口与实现细节分开。例如,将类函数定义和类声明放在不同的文件中。
公有接口表示设计的抽象组件————————————类声明
将实现细节放在一起并将细节与抽象分开(封装)——类函数定义
防止程序直接访问数据-》数据隐藏
public (都可以访问)
private(数据隐藏:数据部分的访问状态时私有的,这意味这程序不能直接访问数据成员,只能通过成员函数来访问数据成员)
protected(与private类似,区别只有在基类派生的类中才会表现出来)
由于隐藏数据时OOP的主要目标之一,通常将数据项放在私有部分,组成类接口的成员函数放在公有部分。
#ifndef 来访问多次包含包含同一个文件
#ifndef <标识>
...
#endif
#ifndef起到的效果是防止一个源文件两次包含同一个头文件,而不是防止两个源文件包含同一个头文件。事实上,防止同一头文件被两个不同的源文件包含这种要求本身就是不合理的,头文件存在的价值就是被不同的源文件包含。
假如你有一个C源文件,它包含了多个头文件,比如头文件A和头文件B,而头文件B又包含了头文件A,则最终的效果是,该源文件包含了两次头文件A。如果你在头文件A里定义了结构体或者类类型(这是最常见的情况),那么问题来了,编译时会报大量的重复定义错误。
基本与常规函数定义类似,有两个特征:
像这种方式声明和定义的类函数——>const成员函数
只要类方法不修改调用对象,就应该声明为const
this为对象的地址,*this为对象本身
当类成员函数涉及到两个对象时,需要使用this指针
每个成员函数(包括构造函数和析构函数)都有一个this指针,this指针指向调用对象。
如果在函数后面加上const(const成员函数),将this限定为从const,则不能使用this来修改对象的值。
返回类型为引用(* this 专门用于表示当前对象的地址)——返回的时调用对象本身而不是副本
最好在创建对象时对它进行初始化,C++提供了一个特殊的成员函数——类构造函数,专门用于构造新对象、将值赋给它们的数据成员(在创建类对象时被调用)。
通过函数重载,可以创建多个同名的构造函数,条件是他们的 参数列表 不同
默认构造函数 (如果没有提供任何构造函数,c++将自动提供默认构造函数,但是为类定义了构造函数之后,程序员就必须为其提供默认构造函数)
构造函数是特殊的成员函数,只要创建类类型的新对象,都要执行构造函数,其目的是保证每个对象的数据成员具有合适的初始值。
在构造函数创建对象后,程序负责跟踪该对象,直到其过期为止。对象过期时,程序将自动调用析构函数。析构函数将完成清理工作,如果构造函数中使用new来分配内存,那么析构函数将使用delete来释放这些内存。
构造函数和析构函数都可以没有返回值和声明类型。
此外,析构函数还可以没有参数。
函数多态(函数重载)指的是可以有多个同名的函数,因此对函数的名称进行了重载。
特征标——函数的参数列表(特征标相同==参数数目和类型相同+参数的排列顺序相同(与变量名无关))
注意点:
运算符重载是一种形式的C++多态。
重载限制:
// 重载=运算符
CMatrix & CMatrix::operator=(const CMatrix & mIn)
{
Release();
m_nRow=mIn.m_nRow;
m_nCol=mIn.m_nCol;
m_pData=new double[m_nRow*m_nCol];
memcpy(m_pData,mIn.m_pData,sizeof(double)*m_nRow*m_nCol);
return *this;
}
// 重载+=运算符 写法一(使用时只能写一种写法)
CMatrix & CMatrix:: operator+=(const CMatrix &b)
{ // 该函数隐式地访问一个对象,显式地访问另一个对象,并返回其中一个对象的引用
if(m_nRow==b.m_nRow&&m_nCol==b.m_nCol)
{
for(int i=0;i<m_nRow*m_nCol;i++)
{
m_pData[i]=m_pData[i]+b.m_pData[i];
}
}
return *this;
}
// 重载+=运算符 写法二(使用时只能写一种写法)
CMatrix & CMatrix::operator+=(const CMatrix &a,const CMatrix &b)
{
CMatrix c;
if(a.m_nRow==b.m_nRow&&a.m_nCol==b.m_nCol)
{
c.Create(a.m_nRow,a.m_nCol);
for(int i=0;i<a.m_nRow*a.m_nCol;i++)
{
c.m_pData[i]=a.m_pData[i]+b.m_pData[i];
}
}
return c;
}
// 重载<<运算符
ostream & operator<<(ostream &out, const CMatrix & s)
{
out<<s.m_nRow<<"\t"<<s.m_nCol<<"\t";
for(int i=0;i<s.m_nRow*s.m_nCol;i++)
out<<s.m_pData[i]<<"\t";
return out;
}
// 重载>>运算符
istream & operator>>(istream &in, CMatrix & s)
{
if(s.m_pData)
{
delete[] s.m_pData;
s.m_nRow=0;
s.m_nCol=0;
}
in>>s.m_nRow>>s.m_nCol;
s.m_pData = new double[s.m_nRow*s.m_nCol];
for(int i=0;i<s.m_nRow*s.m_nCol;i++)
{
in>>s.m_pData[i];
}
return in;
}
CMatrix & CMatrix::operator+(const CMatrix &a,const CMatrix &b)
{
CMatrix c;
if(a.m_nRow==b.m_nRow&&a.m_nCol==b.m_nCol)
{
c.Create(a.m_nRow,a.m_nCol);
for(int i=0;i<a.m_nRow*a.m_nCol;i++)
{
c.m_pData[i]=a.m_pData[i]+b.m_pData[i];
}
}
return c;
}
bool & CMatrix::operator==(const CMatrix &b)
{
bool flag=true;
if(m_nRow==b.m_nRow&&m_nCol==b.m_nCol)
{
for(int i=0;i<m_nRow*m_nCol;i++)
{
if(m_pData[i]!=b.m_pData[i])
flag=false;
}
}
return flag;
}
double & CMatrix::operator[](int nIndex){
return m_pData[nIndex];
}
double & CMatrix::operator()(int i,int j){
return m_pData[i*m_nRow+j];
}
通过让函数成为类的友元,可以赋予该函数与类的成员函数相同的访问权限。
C++是如何处理内置类型转换:
将一个标准类型变量的值赋给另一种标准类型的变量时,如果这两种类型兼容,则C++自动将这个值转换为接收变量的类型。
// 自动转换
int side = 3.33; // double value 3.33 converted to type int 3
// 强制转换
int * p =(int *) 10; // ok, p and (int *) 10 both pointers
CMatrix::operator double() const
{
// 不需要返回值,这个是隐式类型转换
// 虽然没有声明返回类型,但是这个函数也将返回所需的值。
double sum=0;
for(int i=0;i<m_nRow*m_nCol;i++)
{
sum+=m_pData[i];
}
return sum;
}
注意:不要将静态成员的定义放在头文件中,除非保证该头文件不会被两个不同的源文件包含,不然会报重复定义错误,相当于是在两个源文件中都定义了同一个变量。对于这种同一头文件被不同源文件包含的情况,使用#ifndef或者#pragma once是没用的。这种预编译宏是为了解决一个源文件两次包含同一个头文件的问题。
同时,对静态数据成员的定义也不能放在main()函数里,否则编译报错:error C2655: “Box::height”: 当前范围内的定义或重新声明非法。正确的做法,就如上面所说,把它放在定义类的成员函数的源文件中。
原文链接:https://blog.csdn.net/fb_941219/article/details/101024110
// 声明cpp
static int GetDim();
// 实现cpp
int CMatrix::GetDim()
{
cout<<"GetDim()" <<endl;
return m_nDim;
}
#ifndef CMATRIX_R
#define CMATRIX_R
#include
#include
using namespace std;
class CMatrix
{
public:
CMatrix():m_pData(0),m_nCol(0),m_nRow(0){}
CMatrix(int nRow,int nCol,double * pData=NULL);
bool Create(int nRow,int nCol);
void Release();
~CMatrix();//析构函数
bool Read(string strPath);
bool Write(string strPath) const;
inline double Get(int nIndex) const;
inline double Get(int nRow,int nCol) const;
CMatrix & Set(int nIndex,double dVal);
CMatrix & Set(int nRow,int nCol,double dVal);
CMatrix &operator=(const CMatrix &mIn);
CMatrix &operator+=(const CMatrix &b);
bool &operator==(const CMatrix &b);
double &operator[](int nIndex);
double &operator()(int i,int j);
//CMatrix &operator+(const CMatrix &a,const CMatrix &b);
operator double() const;
static int GetDim();
private:
// 友元函数
// 直接定义(不需要声明)
friend ostream & operator<<(ostream &out, const CMatrix & s)
{
cout<<"重载<<" <<endl;
out<<s.m_nRow<<"\t"<<s.m_nCol<<"\t";
for(int i=0;i<s.m_nRow*s.m_nCol;i++)
out<<s.m_pData[i]<<"\t";
return out;
}
friend istream & operator>>(istream &in, CMatrix & s)
{
cout<<"重载>>" <<endl;
if(s.m_pData)
{
delete[] s.m_pData;
s.m_nRow=0;
s.m_nCol=0;
}
in>>s.m_nRow>>s.m_nCol;
s.m_pData = new double[s.m_nRow*s.m_nCol];
for(int i=0;i<s.m_nRow*s.m_nCol;i++)
{
in>>s.m_pData[i];
}
return in;
}
friend CMatrix operator+(const CMatrix &a,const CMatrix &b)
{
cout<<"重载+" <<endl;
CMatrix c;
if(a.m_nRow==b.m_nRow&&a.m_nCol==b.m_nCol)
{
c.Create(a.m_nRow,a.m_nCol);
for(int i=0;i<a.m_nRow*a.m_nCol;i++)
{
c.m_pData[i]=a.m_pData[i]+b.m_pData[i];
}
}
return c;
}
/*
//这部分在cmatrix.cpp中定义 需要先声明
friend CMatrix operator+=(const CMatrix &a,const CMatrix &b)
{
CMatrix c;
if(a.m_nRow==b.m_nRow&&a.m_nCol==b.m_nCol)
{
c.Create(a.m_nRow,a.m_nCol);
for(int i=0;i
double * m_pData;
int m_nCol;//列数
int m_nRow;//行数
static const int m_nDim=2;//const 修饰成员变量
};
// 内联函数 需要先声明
inline double CMatrix::Get(int nIndex) const
{
cout<<"Get(int)" <<endl;
return m_pData[nIndex];
}
inline double CMatrix::Get(int nRow,int nCol) const
{
cout<<"Get(int,int)" <<endl;
return m_pData[nRow*nCol+nCol];
}
#endif //CMATRIX_H
#include "cmatrix.h"
#include
#include
#include
CMatrix::CMatrix(int nRow,int nCol,double * pData)// 构造函数
{
cout<<"CMatrix(int,int,double)" <<endl;
m_pData=NULL;
Create(nRow,nCol);
if(pData)
{
//memcpy 函数用于 把资源内存(src所指向的内存区域) 拷贝到目标内存(dest所指向的内存区域);拷贝多少个?有一个size变量控制
memcpy(m_pData,pData,sizeof(double)*nRow*nCol);
}
}
CMatrix::~CMatrix()// 析构函数
{
cout<<"~CMatrix()" <<endl;
if(m_pData!=NULL)
{
delete []m_pData;
}
}
CMatrix & CMatrix::Set(int nIndex,double dVal)
{
cout<<"Set(int,double)" <<endl;
m_pData[nIndex]=dVal;
return *this;
}
CMatrix & CMatrix::Set(int nRow,int nCol,double dVal)
{
cout<<"Set(int,int,double)" <<endl;
m_pData[nRow*nCol+nCol]=dVal;
return *this;
}
int CMatrix::GetDim()
{
cout<<"GetDim()" <<endl;
return m_nDim;
}
bool CMatrix::Read(string strPath)
{
cout<<"Read(string)" <<endl;
if(m_pData)
{
delete[] m_pData;
m_pData=NULL;
m_nRow=m_nCol=0;
}
const char* p = strPath.data();
ifstream in(p);
if(in>>m_nRow>>m_nCol)
{
m_pData=new double[m_nRow*m_nCol];
printf("m_nRow=%d m_nCol=%d\n",m_nRow,m_nCol);
printf("m_nRow*m_nCol=%d\n",m_nRow*m_nCol);
for(int i=0;i<m_nRow*m_nCol;i++)
{
printf("i=%d\n",i);
in>>m_pData[i];
/* if(in>>m_pData[i])
{
printf("m_pData[%d]=%d",i,m_pData[i]);
return false;
}
*/
}
return true;
}
else
{
return false;
}
}
bool CMatrix::Write(string strPath) const
{
cout<<"Write(string) const" <<endl;
const char* p = strPath.data();
ofstream out(p);
out<<m_nRow<<"\t"<<m_nCol<<"\n";
for(int i=0;i<m_nRow*m_nCol;i++)
out<<m_pData[i]<<"\t";
return true;
}
bool CMatrix::Create(int nRow,int nCol)
{
cout<<"Create(int,int)" <<endl;
Release();
m_nRow=nRow;
m_nCol=nCol;
m_pData=new double[nRow*nCol];
}
void CMatrix::Release()
{
cout<<"Release()" <<endl;
if(m_pData)
{
delete []m_pData;
m_pData=NULL;
}
m_nRow=m_nCol=0;
}
CMatrix & CMatrix::operator=(const CMatrix & mIn)
{
cout<<"重载=" <<endl;
Release();
m_nRow=mIn.m_nRow;
m_nCol=mIn.m_nCol;
m_pData=new double[m_nRow*m_nCol];
memcpy(m_pData,mIn.m_pData,sizeof(double)*m_nRow*m_nCol);
return *this;
}
bool & CMatrix::operator==(const CMatrix &b)
{
cout<<"重载==" <<endl;
bool flag=true;
if(m_nRow==b.m_nRow&&m_nCol==b.m_nCol)
{
for(int i=0;i<m_nRow*m_nCol;i++)
{
if(m_pData[i]!=b.m_pData[i])
flag=false;
}
}
return flag;
}
CMatrix & CMatrix:: operator+=(const CMatrix &b)
{
cout<<"重载+=" <<endl;
if(m_nRow==b.m_nRow&&m_nCol==b.m_nCol)
{
for(int i=0;i<m_nRow*m_nCol;i++)
{
m_pData[i]=m_pData[i]+b.m_pData[i];
}
}
return *this;
}
/*
CMatrix & CMatrix::operator+(const CMatrix &a,const CMatrix &b)
{
CMatrix c;
this->c = c;
if(a.m_nRow==b.m_nRow&&a.m_nCol==b.m_nCol)
{
c.Create(a.m_nRow,a.m_nCol);
for(int i=0;i
double & CMatrix::operator[](int nIndex){
cout<<"重载下标操作符([]" <<endl;
return m_pData[nIndex];
}
double & CMatrix::operator()(int i,int j){
cout<<"重载调用操作符()" <<endl;
return m_pData[i*m_nRow+j];
}
CMatrix::operator double() const
{
//不需要返回值,这个是隐式类型转换
cout<<"重载double()" <<endl;
double sum=0;
for(int i=0;i<m_nRow*m_nCol;i++)
{
sum+=m_pData[i];
}
return sum;
}
#include
#include
#include
#include "cmatrix.h"
using namespace std;
int main() {
CMatrix m; //创建对象(类的实例)
double d[10]={1,2,3,6};
CMatrix m1(2,2,d);
m1.Write("out.txt"); //通过 类对象 来调用 类成员函数(方法)
CMatrix m2;
m2.Read("in.txt");
m2.Write("out1.txt");
cout<<m2<<endl;
m2.Set(0,0,3);
int getint=m2.Get(0,0);
printf("getint=%d\n",getint);
m2.Write("out2.txt");
cout<<m2<<endl;
CMatrix a;
a.Read("in.txt");
//CMatrix b(a);
CMatrix b;
b=a;
bool flag=(a==b);
cout<<"flag(a==b)="<<flag<<endl;
bool flag2=(m2==b);
cout<<"flag(m2==b)="<<flag2<<endl;
cout<<"m2 "<<m2<<endl;
cout<<"b "<<a<<endl;
CMatrix c;
c=a+b;
cout<<"a "<<a<<endl;
cout<<"b "<<b<<endl;
a+=b;
cout<<"a+=b "<<a<<endl;
cout<<"c=a+b "<<c<<endl;
cout<<"c[0]"<<c[0]<<endl;
cout<<"c(1,1)"<<c(1,1)<<endl;
double sum=(double)(a);
cout<<"sum="<<sum<<endl;
// double sum=(double)a; //报错
return 0;
}
CMatrix(int,int,double)
Create(int,int)
Release()
Write(string) const
Read(string)
m_nRow=3 m_nCol=3
m_nRow*m_nCol=9
i=0
i=1
i=2
i=3
i=4
i=5
i=6
i=7
i=8
Write(string) const
重载<<
3 3 1 2 3 2 2 2 3 3 3
Set(int,int,double)
Get(int,int)
getint=3
Write(string) const
重载<<
3 3 3 2 3 2 2 2 3 3 3
Read(string)
m_nRow=3 m_nCol=3
m_nRow*m_nCol=9
i=0
i=1
i=2
i=3
i=4
i=5
i=6
i=7
i=8
重载=
Release()
重载==
flag(a==b)=1
重载==
flag(m2==b)=0
m2 重载<<
3 3 3 2 3 2 2 2 3 3 3
b 重载<<
3 3 1 2 3 2 2 2 3 3 3
重载+
Create(int,int)
Release()
重载=
Release()
~CMatrix()
a 重载<<
3 3 1 2 3 2 2 2 3 3 3
b 重载<<
3 3 1 2 3 2 2 2 3 3 3
重载+=
a+=b 重载<<
3 3 2 4 6 4 4 4 6 6 6
c=a+b 重载<<
3 3 2 4 6 4 4 4 6 6 6
重载下标操作符([]
c[0]2
重载调用操作符()
c(1,1)4
重载double()
sum=42
~CMatrix()
~CMatrix()
~CMatrix()
~CMatrix()
~CMatrix()
~CMatrix()