成员类应如何访问成员函数?

时间:2014-06-25 20:23:48

标签: c++ class member

这是一个要找出更好的编程习惯的问题:

在C ++中,我说有两个类,其中一个类是另一个类的成员类,例如

class SomeClass {

 public:

  MemberClass member_class;

  void set_num(double num_) { num_ = num; }

  double num() {return num_; }

 private:

  double num_;

}

我希望成员类能够访问外部类的成员函数,例如

class MemberClass {

 public:

  PrintSquare() {

    cout << num() * num() << endl;

  }

}

我正在努力实现这一目标,以减少我在程序中传递的函数参数的数量。

3 个答案:

答案 0 :(得分:2)

解决此问题的最常见(和IMHO正确)方法是,为包含类引入一个接口(或者甚至更多关注特定方法集的接口),并将其传递给'inner施工的班级成员:

struct Interface {
  virtual void set_num(double num_) = 0;
  virtual double num() const = 0;
  virtual ~Interface() {}
};

class MemberClass {
public:
    MemberClass(Interface& interface) : interface_(interface) {}
    PrintSquare() {
        cout << interface_.num() * interface_.num() << endl;
    }

private:
    Interface& interface_;
};

class SomeClass : public Interface {
public:
    MemberClass member_class;

    SomeClass() : member_class(*this), num_() {}

    virtual void set_num(double num_) { num_ = num; }
    virtual double num() const { return num_; }
    virtual SomeClass() {}

private:
    double num_;
};

注意:MemberClass构造函数定义调用时,调用接口的方法虽然会失败(有运行时异常)。

答案 1 :(得分:1)

尽管Kerrek的答案非常有趣,但他自己已经说过这通常不是一条路。如果可能的话,通常的做法是使内部类嵌套在外部类中。如果内部的一个需要以一种嵌套连接看起来很自然的方式访问外部的那个,那么这就是要走的路。然后构造Inner对象需要引用它所属的对象,以便能够在其父对象上调用函数:

class Outer
{
    class Inner
    {
        Outer &parent; // consider constness
    public:
        Inner(Outer &_parent); //initializes the parent-reference
        void innerFunction(); // can call members of parent    
    };

    Inner inner;
public: 
    Outer(): inner(*this) { ... } // initialize inner
};

根据您使用的标准,innerFunction现在可以访问Outer(C ++ 03)的所有公共成员,甚至所有私人成员(C +) +11)。另见本主题: C++ nested classes - inner/outer relationship

编辑:做了快速测试,我的编译器(gcc 4.7.2)也允许访问使用旧标准的私有成员。也许有人可以对此发表评论...

答案 2 :(得分:0)

如果你的类都是标准布局,那么你可以利用C ++所做的一些布局保证,即标准布局类型的on对象可以被视为它自己的第一个成员。例如:

struct Foo
{
    int a;

    void barely_legal();
};

struct Bar
{
    Foo x;
    int y;
};

#include <type_traits>

void Foo::barely_legal()
{
    static_assert(std::is_standard_layout<Foo>::value, "Foo");
    static_assert(std::is_standard_layout<Bar>::value, "Bar");

    Bar * p = reinterpret_cast<Bar *>(this);

    ++p->y;
}

这在最好的情况下是不寻常的,在最坏的情况下是残酷的,所以请不要写这样的代码,除非你有充分的理由这样做。 (我知道有理由这样做的人,但我不会拒绝他们。)