注册 登录
编程论坛 C++教室

想不通 ~类内私有成员的一连串问题

dracovash 发布于 2009-07-31 18:29, 869 次点击
问题 1
有以下定义
class A
{
public:
    //.......
private:
    A inside_object;
    //.......
};


这样的话 A对象的私有成员里会有一个A类型的对象,名叫inside_object
但是这个名为inside_object的私有成员自己也会有一个A的对象名为inside_object的私有成员 ~~~
然后循环往复  岂不是要耗光内存  ~~?~~~~
 ~~~额额额额  ~想不通吖~~~~谁明白给我讲讲呗  ~~

问题 2
class A
{
      //  ...
};

class B
{
private:
    A myAobj;
public:
     //......
};
就是如果类A没有写A()这样的不接受参数的构造函数,那么类B内 myAobj这样的声明没问题吧  ?对myAobj的初始化是不是只能放在B的构造函数里呢  ?~
那么 类外可以像A myAobj;这样声明对象么~?

问题 3……

class A
{
private:
    int a;
    //....
public:
    //....
    void fun(int num=a);
};

实际情况是函数fun需要参数num来做运算,这时可以用对象内私有成员a,也可以从外部传递参数。但是这样做编译不通过,说只能把a声明成静态成员。但是我不想这么做,应该怎么解决呢~?
还有  如果a被声明成一个函数指针,也就是说fun函数需要一个函数指针做参数(可以是一个算法公式之类的),这种情况下要怎么办呢?~

以上问题  求解决方法和简单实例代码~~~

[[it] 本帖最后由 dracovash 于 2009-7-31 18:43 编辑 [/it]]
12 回复
#2
mfkblue2009-07-31 19:32
个人理解,错了不要跨省啊
第一个:类对象只是一个首地址,这第一个问题要看你的构造函数怎么给这个私有成员赋初值。
第二个:如果类A构造函数是带参数的,类B的构造函数一定要为类A参数赋值.格式大概是
B::B():a(x) 假设类A构造函数需要一个参数。
类外可以像A myAobj 。这样就是全局对象了。
第三个:fun已经是成员函数了,调用自己类的私有成员,应该没什么问题吧.
#3
木马2009-07-31 20:03
留下脚印
#4
dracovash2009-07-31 20:03
回复 2楼 mfkblue
我的本意:
我做了一个矩阵的数据结构。那个fun其实是一个查询函数,原型是这样的:
template <class T>
CEleObj <T> * rec <T>::get(UINT,UINT,miterator <T> * =recite);
最后一个参数提供迭代器接口。可以使用内部的迭代器,也可以从外部传入更加便利的迭代器。
向第三个问题所说,私有成员int a代表的是内部声明的迭代器对象,我需要随时改变迭代器对象里面的内容,所以我不可能声明成const常量类型。其次每个矩阵都有自己的内部迭代器,所以不能声明成static类型。我这个确实是指针,也确实没通过编译~~~~
#5
mfkblue2009-07-31 20:39
回复 4楼 dracovash
这么麻烦的类我还没也写过,你比我还厉害勒。
这个不知道是不是你要的.

#include <iostream.h>
class A
{
public:
    void fun();
    void show()
    {cout<<*p<<endl;}
private:
    int *p;
    int a;
};


void A::fun()
{
        
    p=&a;
    *p=5;
}

void main()
{
    A a;
    a.fun();
    a.show();

}
#6
dracovash2009-07-31 22:41
回复 5楼 mfkblue
恩恩   ~~你写的比较简单~~~~我写的很复杂  现在在做策划  做完才能开始写……现在就是遇到这几个问题了  ~
#7
dracovash2009-07-31 22:43
共享一下  ……
typedef unsigned short int UINT;

//迭代器方向
enum ITE_DIR  
{
    ITD_RIGHT,
    ITD_DOWN ,   
    ITD_LEFT ,     
    ITD_UP   
};

//矩阵扩充方向
enum AUG_DIR
{
    AUG_RIGHT,
    AUG_DOWN ,
    AUG_LEFT ,
    AUG_UP   
};

//最终类对象生成元素之一
enum REC_TYPE  
{
    RT_LIST  ,   
    RT_REC   ,   
    RT_BOARD ,  
    RT_CUBE   
};
//输出风格
enum PRINT_TYPE
{
    PRT_NORMAL ,//普通输出
    PRT_ADD //输出地址
};

template<typename>class CEleObj;//基础元素类
template<typename>class rec;//基础矩阵类
template<typename>class recboard;//基础矩阵板类
template<typename>class reccube;//基础矩阵块类
template<typename>class miterator;//迭代器
class POINT;//点类

template<typename T>
class DIRP
{
public:
    CEleObj<T> * POINT_UP;
    CEleObj<T> * POINT_DOWN;
    CEleObj<T> * POINT_RIGHT;
    CEleObj<T> * POINT_LEFT;
};


class POINT
{
public:
    UINT x,y;
    POINT(UINT _x,UINT _y):
    x(_x),y(_y){}
    ~POINT(){}

};
template<typename T>
class CEleObj
{
public:
    CEleObj(){}
    CEleObj(T & rele):ele(rele){}
    T get(){return ele;}
    void set(T & rele){ele=rele;}

    DIRP<T> DP;
private:
    T ele;
};

template<typename T>
class miterator
{
    CEleObj<T> * nowplace;//当前迭代指针
    CEleObj<T> * phead;//头指针
    POINT nowpoint;//指针当前坐标
    
    miterator(const CEleObj<T> *);
public:
    miterator(const rec<T> &);
    ~miterator(){}
    bool next(ITE_DIR);//迭代函数
    bool locate(UINT,UINT);//迭代器定位
    bool locate(POINT);
};

template<typename T>
class rec
{
    UINT recx,recy;
    CEleObj<T> * headele;
    miterator<T> * recite;
public:
    friend class miterator<T>;
    rec();
    rec(UINT,UINT);
    rec(const rec &);//拷贝构造函数
    ~rec();


    bool insert(UINT,UINT,const T &);//插入元素
    bool edit(UINT,UINT,const T &);
    bool edit(POINT,const T &);
    CEleObj<T> * get(UINT,UINT);//查询算法~
    CEleObj<T> * get(POINT);
    bool augment(rec<T> &,AUG_DIR);//扩充算法:直接对接
    bool delrec();//删除整个矩阵
    void print(PRINT_TYPE);//打印整个矩阵

    bool _locate(UINT,UINT);//内部迭代器重定位
    bool _locate(POINT);
    bool _locate();

    UINT getx(){return recx;}
    UINT gety(){return recy;}
};

[[it] 本帖最后由 dracovash 于 2009-7-31 22:46 编辑 [/it]]
#8
粉萦月2009-08-01 15:12
你们都好厉害呀!为什么我连最基础的都晕呀???
#9
pangding2009-08-01 18:20
回复 4楼 dracovash
第三个缺省参数的那个问题,语法上好像确实只能提供一个常量做为缺省的值。你可以就用默认构造函数构造第三个参数,之后在函数里检查是不是那个默认的,如果是,就再用a赋值一下。

第一个问题,我觉得挺奇怪,我想着这么定义应该有语法错误(至少struct不允许这种自包含),如果你编译通过了,我就不知道怎么回事了,自己做点实验试试呗~(眼下我用的不是我的电脑,没有编译器)
第二个问题,mfk说的是对的,A必需提供一个默认构造函数(以供B默认调用)。或者就得由B提供参数,以初始化内部的A对象。
#10
pangding2009-08-01 18:25
回复 9楼 pangding
哦,那第三个还有一个很简单的方法,就是用函数重载(这个方法比较好,我觉得)。
你先编一个必须提供第三个参数的函数。编好了之后,再编一个可以传两个参数的函数,把第三个参数赋值成a,内联调用一下那个函数就行了。

像这样:
fun(int n) // 必须要一个int参数
{
    //...
}

inline fun()
{
    fun(a) // 把a作为默认的参数传过去。
}
#11
mfkblue2009-08-01 20:34
回复 10楼 pangding
昨天没试,果然类的私有成员是不可以包含该类的对象。
#12
tbls2009-08-01 20:40
关于问题1,好像编译不能通过,你可以声明成一个指针。
关于问题2,myAobj的初始化只能放在类A中,在类B中只能给A传递参数,然后由A根据参数来决定怎样初始化,如果你没有重载无参数的构造函数,那么A将调用默认的构造函数。
关于问题3,这是一个类概念的问题,类的私有变量成员其实质是一个声明,编译器还没有对他们分配内存,也就是说在定义的时候其实他们都不存在。你不能用一个不存在的变量去给函数的参数赋默认值。之所以要你先声名为static,就是可以在定义时为变量分配空间。
#13
dracovash2009-08-01 22:22
同志们我都明白了  ~谢谢大家  ~分我只给第一个回答问题的了  ~呵呵   ~~~
C++学起来还是蛮有意思的  ~做点自己的东西出来感觉很棒   ~~加油加油~~
1