C++:不同类对象之间访问数据的3种简单常用方法

         C++编程中经常出现两个不同的类对象之间相互访问数据的需要,但是成员变量不是public形式,无法直接访问相应的变量,抛开全局变量不谈,常用的方法有:1类封装留下的接口函数、2友元机制、3类静态成员变量。

回顾:

      类是面向对象程序设计语言中的一个概念。类是对某个对象定义,它含有有关对象的动作方式的信息,包括他的名称,方法,属性和事件

类成员有3种不同的访问权限
1 公有(public) 成员可以在类外访问  
2 私有(private) 成员只能在累的成员函数之间进行访问  
3 保护(protected) 只能在类的成员以及派生类的成员函数之间  
       

简单理解封装和接口接口,简单说就是public的方法,供外部使用,通过这些public的方法,可以操作内部数据,所以称之为接口。 封装,一个类是由数据与方法组成的,将数据和方法放在一起,就是封装。 

知识点补充:

I).构造函数后面的冒号就是初始化,而括号里面的等于号并不是初始化,而是变量生成以后的赋值而已(永远都是2个步骤)

    

  • 有四种情况下应该使用初始化表达式来初始化成员:
  • 1:初始化const成员
  • 2:初始化引用成员
  • 3:当调用基类的构造函数,而它拥有一组参数时
  • 4:当调用成员类的构造函数,而它拥有一组参数时。

II) 作用域符号 :: 的前面一般是类名称,后面一般是该类的成员名称,C++为例避免不同的类有名称相同的成员而采用作用域的方式进行区分

      如:A,B表示两个类,在A,B中都有成员member。那么      A::member就表示类A中的成员member      B::member就表示类B中的成员member

III) 全局作用域符号:当全局变量在局部函数中与其中某个变量重名,那么就可以用 :: 来区分如

       char    zhou;    //全局变量

       void    sleep()

   {

        char    zhou;    //局部变量

        char(局部变量) = char(局部变量) *char(局部变量) ; 

       ::char(全局变量) =::char(全局变量) *char(局部变量);

    }

IV) :: 是C++里的“作用域分解运算符”

       比如声明了一个类A,类A里声明了一个成员函数voidf(),但没有在类的声明里给出f的定义,那么在类外定义f时,就要写成voidA::f(),表示这个f()函数是类A的成员函数。例如

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

class CA {

public:

  int ca_var;

  int add(int a, int b);

  int add(int a);

};

 

//那么在实现这个函数时,必须这样书写:

int CA::add(int a, int b)

{

  return a + b;

}

 

//另外,双冒号也常常用于在类变量内部作为当前类实例的元素进行表示,比如:

int CA::add(int a)

{

  return a + ::ca_var;

}

 

//表示当前类实例中的变量ca_var。

 

C++代码实接口封装的方法:

1.对原功能的代码在打包一层

由于我们不想暴露AImpl.h中,故对其封装,即在A.h和A.cpp中对其包一层。
我们甚至在A.h中都不需要声明 AImpl *imp_的,在A.h中可以只声明一个void *imp_,在A.cpp中将该void *指针转换成Almpl *即可。

AImpl.h

class AImpl
{
public:
    ...
 
private:
    int a;
    ...
};

A,h

class AImpl;
 
class A
{
public:
    A();
    ~A();
    void f();
 
private:
    AImpl *imp_; //
};

 A.CPP

#include "AImpl.h"
#include "A.h"
 
A::A()
: imp_(new AImpl)
{
}
 
A::~A()
{
    delete imp_;
}
 
void A::f()
{
    imp_->f();
}

 

2.父类声明为虚函数

    下面通过一个具体的实例进行接口的是实现。

                                                          C++:不同类对象之间访问数据的3种简单常用方法_第1张图片

base.h

#ifndef BASE_H
#define BASE_H
#include "ibase.h"

class CBase :
        public Ibase
{
 public:
   CBase(void);
   virtual ~CBase(void);
   virtual  void Release();
   virtual  void  Do();
private:
   int m_nID;
};
#endif // BASE_H

ibase.h

#ifndef IBASE_H
#define IBASE_H
class Ibase{
  public:
    Ibase(void);
    virtual ~Ibase(void); //虚函数,meiyou7函数体
    virtual void Release()=0;//纯虚函数需要加=0
    virtual void  Do()=0;
};
Ibase *Create();
#endif // BASE_H

base.cpp

#include "ibase.h"
#include "base.h"
using namespace std;

CBase::CBase(void)
{
   m_nID=0;
}
CBase::~CBase(void)
{


}
void CBase::Release()
{
    delete  this;
}
void  CBase::Do()
{
    m_nID++;
}

ibase.cpp

 

#include  "ibase.h"
#include  "base.h"
//实现
Ibase::Ibase()
{
    //构造函数
}
Ibase::~Ibase()
{
    //析构函数
}
Ibase *Create()
{
    return  new CBase;
}

main,cpp

#include 
#include  "ibase.h"
using  namespace  std;
int main()
{
 Ibase *poBase=Create();
 if(NULL!=poBase)
 {
     poBase->Do();
     poBase->Release();
     poBase=NULL;

 }
 return 0;
}

2、通过友元机制

在一个类中,可以利用关键字friend将别的模块(一般函数、其他类的成员函数或其他类)声明为它的友元,这样这个类中本来隐藏的信息就可以被友元访问j。如果友元是一般函数或类的成员函数,称为友元函数;如果友元是一个类,则称为友元类,友元类的所有成员函数都成为友元函数。

 
class B
{
//B类的成员声明
friend float f(B&x,B&y);//友元函数声明
friend class A;//声明A为B的友元类
};
 在B类声明f函数为友元函数,则在f函数中通过对象名可直接访问B类所有的数据成员。同时在B类声明A类为友元类,则A类的所有成员函数都是B类的友元函数,都可以访问B类的私有和保护成员。采用友元类共享数据机制,使友元类成员函数可以通过对象名直接访问到隐藏的数据,从而使程序达到高效协调工作。在较为复杂的问题中,实现不同类之间的数据共享,友元类的使用也是必不可少的选择。友元在类之间、类与普通函数之间共享了内部封装的数据的同时,必然会对类的封装性带来一定的破坏。因此在程序设计中使用友元,要在共享和封装之间找到一个恰当的平衡点,从而达到提高程序效率同时,将程序隐患降来最低。

3、通过类的静态成员变量

 C++中使用静态成员可以实现同一类的不同对象之间共享数据 j。类的普通数据成员在类的每一个对象都有一个拷贝,就是说每个对象的同名数据成员可以分别存储不同数值,这就保证对象拥有自身区别其他对象的特征的需要。静态数据成员是类的数据成员的一种特例,采用static关键字来声明;每个类只有一个拷贝,由该类的所有对象共同维护和使用,从而实现了同一类的不同对象之间的数据共享。

例如:

#include
using namespace std;
class sample
{
private:
static char m_sArray[10];
public:
       sample(){ cout << "default constructor! "<< endl;}
sample(sample & s){ cout <<"copy constructor! " << endl;}
       void show(void) { cout << m_sArray << endl;}
void input(void) { cin.get(m_sArray, 10);}
};
char sample::m_sArray[10] = "I am a engineer";
int main(void)
{
sample e1;
       e1.show();
       sample e2(e1);
e2.show();
e2.input();
e1.show();
}
//运行结果如下:
default constructor!
I am a engineer
copy constructor!
I am a engineer
this is my job
this is my job
静态成员变量m_sArray确实起到了在不同对象间共享的作用!不过由于其是静态属性,内存是在全局/静态区域开辟的,属于栈内存区,内存大小使用受限。如果能动态从堆中申请内存,则可以使用大内存空间了。

有一学生类:

class engineer
{
Private:
im ID :
char nalne;
static count;//静态数据成员,用来存放“人数”
string name;
}
如果程序中需要统计学生人数,这个数据存放在什么地方呢?若以类外的全局变量来存放,不能实现数据的隐藏,若在类中增加一个数据成员用以存放人数,必然在每一个对象中都存储一副本,这样不仅冗余,而且每个对象分别维护一个“人数”,势必造成数据的不一致性。因此,比较好的方案是在engineer类中增加一个静态数据成员。static count用来存放学生“人数”。
 

你可能感兴趣的:(C++:不同类对象之间访问数据的3种简单常用方法)