父类中子类的实例

发布于 2024-10-04 14:32:10 字数 547 浏览 3 评论 0原文

我在类层次结构中有两个类,其中父类需要有一个从它派生的类的实例作为成员变量。举个例子:

class B;

class A {
public:
    B* binst;

    A();
};

class B : public A {
};

A::A() {
    binst = new B;
}

显然,这会导致构造函数中的无限递归,因为要创建一个新的 B,您必须调用 A 的构造函数,这会创建一个新的 B,该新的 B 又调用 A 的构造函数,如此循环下去。

有办法解决这个问题吗?我遇到的问题是 A 中必须有 B,但 B 必须从 A 派生,并且没有办法阻止这种情况。

要了解为什么我需要这样做,请考虑脚本语言的面向对象层次结构(例如 python、ruby 或 lua 等):

  1. 任何事物的所有实例都派生自基类 Object。
  2. 对象有一个方法查找表,它是MethodTable的一个实例。
  3. MethodTable 是从 Object 派生的,并且必须是这样,以便脚本语言能够对其进行操作。

I have two classes in a class hierarchy where a parent class needs to have an instance of a class derived from it as a member variable. As an example:

class B;

class A {
public:
    B* binst;

    A();
};

class B : public A {
};

A::A() {
    binst = new B;
}

Obviously, this causes an infinite recursion in the constructors, because to create a new B you have to call A's constructor, which creates a new B which calls A's constructor, and so ad infinitum.

Is there a way around this? The problem I'm having in this is that A has to have a B in it, but B must be derived from A, and there's not a way to prevent that.

To get an idea of why I need to do this, consider an object oriented hierarchy for a scripting language (like python or ruby or lua, etc):

  1. All instances of anything are derived from a base class, Object.
  2. Object has a method lookup table, which is an instance of MethodTable.
  3. MethodTable is derived from Object, and must be, for the scripting language to be able to operate on it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

¢蛋碎的人ぎ生 2024-10-11 14:32:11
  • “对象有一个方法查找表”
  • “方法表派生自对象”

抛开编码问题,从概念的角度来看,这些语句在一起真的有意义吗?方法表是否应该有自己的方法表,然后方法表又有自己的方法表...等等?

我想说,听起来您需要稍微重构一下您的概念。例如,也许对象本身应该以某种方式负责公开其 MethodTable 成员的必要部分。因此不需要 MethodTable 本身是一个对象。 (可能还有其他各种可行的设计。如果不深入了解实际项目,很难说。)

  • "Object has a method lookup table"
  • "MethodTable is derived from Object"

Putting aside coding concerns, do these statements really make sense together from even a conceptual standpoint? Should a MethodTable have its own MethodTable which then has its own MethodTable... etc?

I'd say it sounds like you need to refactor your concepts a bit. For instance, perhaps Object itself should somehow be responsible for exposing the necessary pieces of its MethodTable member. Thus not requiring MethodTable itself to be an Object. (There may be various other feasible designs too. It's hard to say without deeper knowledge of the actual project.)

意中人 2024-10-11 14:32:11

编辑:通常,编译器/实现内部类型不派生自语言相关类型。如果您查看 Java 的内部结构,您会发现它们的继承实现不会派生自 Object。对象是一种语言结构,它是语言接口的一部分。方法表是实现的一部分。方法表不应该由语言操作,而应该由实现操作。

此外,强制从 Object 派生是一件愚蠢的事情,之所以会发生这种情况,是因为您没有考虑语言设计以及用户如何正确编写通用代码。在 Lua 或 Python 等动态类型语言中尤其如此。

Edit: Typically, compiler/implementation-internal types don't derive from language-dependent types. If you look at the internals of Java, their inheritance implementation won't derive from Object. Object is a language construction, it's part of your language's interface. A method table is part of the implementation. A method table should not be operated on by the language, it should be operated on by the implementation.

Moreover, enforced deriving from Object is a stupid thing to do and it happens because you didn't consider the language design and how the users were going to write generic code properly. This is especially true in dynamically typed languages like Lua or Python.

豆芽 2024-10-11 14:32:11

对象可以有一个私有 MethodTableImpl 成员和一个返回 MethodTable 的公共 getter。 MethodTable 包含 MethodTableImpl 并派生自 Object。

Object could have a private MethodTableImpl member and a public getter that returns a MethodTable. MethodTable contains a MethodTableImpl and derives from Object.

等待圉鍢 2024-10-11 14:32:11

我不知道你的类的目的,但这里有一个建议:

class A
{
public:
    virtual void func DoIt () = 0;
    ...
};

class B : public virtual A
{
public:
};

class C : public virtual A ,B
{
    void func DoIt () { /* statements */ }
};

现在 A 类只有 1 个实例。

I don't know the purpose of your classes but here is a suggestion :

class A
{
public:
    virtual void func DoIt () = 0;
    ...
};

class B : public virtual A
{
public:
};

class C : public virtual A ,B
{
    void func DoIt () { /* statements */ }
};

now there is only 1 instance of class A.

稳稳的幸福 2024-10-11 14:32:11

准确理解您是否试图通过此构造实现目标将很有帮助。

正如您自己所指出的,这实际上就像让 A 的构造函数构造 A 的实例,这是堆栈溢出的不可避免的路径。

更通用的解决方案是为指向 A 实例的指针提供一个 set_subclass 方法,然后可以由 A 的任何子类(而不仅仅是 B)填充该实例。

class A {
public:
    A();
    virtual ~A();

    set_subclass(A* sub) { subclass = sub; }
private:
    A* subclass;
};

It would be helpful to understand exactly are you trying to achieve via this construct.

As you've noted yourself, this is effectively like having A's constructor construct an instance of A, and that's an unavoidable path to stack overflow.

A more general solution would be to provide a set_subclass method for a pointer to an instance of A, which could then be populated by any subclass of A, not just B.

class A {
public:
    A();
    virtual ~A();

    set_subclass(A* sub) { subclass = sub; }
private:
    A* subclass;
};
桃气十足 2024-10-11 14:32:11
// List(1) or Stream(2) using inheritance
struct B;

struct A { 
  B *inst; 
  A(B *inst_) : inst(inst_) {}
  A()  : inst(0) {}
};

struct B : A {
  B(B *_inst) : A(inst) {}
  // chose option 1 or 2
  B() : A() {}       // option 1: List
  B() : A(0) {}      // same as above
  B() : A(this) {}   // option 2: Stream
};

auto B3 = new B(new B( new B));
// This is either a length 3 list (1)
// or a stream (2) implemented by self ref 3rd element
// List(1) or Stream(2) using inheritance
struct B;

struct A { 
  B *inst; 
  A(B *inst_) : inst(inst_) {}
  A()  : inst(0) {}
};

struct B : A {
  B(B *_inst) : A(inst) {}
  // chose option 1 or 2
  B() : A() {}       // option 1: List
  B() : A(0) {}      // same as above
  B() : A(this) {}   // option 2: Stream
};

auto B3 = new B(new B( new B));
// This is either a length 3 list (1)
// or a stream (2) implemented by self ref 3rd element
杀お生予夺 2024-10-11 14:32:11

您可以为类 A 创建一个构造函数,它接受指向类 B 的对象的指针,并分配此指针而不是分配新的 B:

A::A(B* b) : binst (b) {}

在类 B 的构造中,您在 A 的构造函数中传递“this”:

B::B() : A(this) {} 

编译器可能会抱怨一下,但你可以尝试。 (不过它很难看。)

请注意,您不能使用 binst 指针在 A 的构造函数中访问对象 B,因为它尚未完全构造。

You can make a constructor for class A which accepts a pointer to an object to class B and assign this pointer instead of allocating a new B:

A::A(B* b) : binst (b) {}

And in the construct of class B you pass 'this' in constructor of A:

B::B() : A(this) {} 

The compiler will probably complain about it, but you can try. (It is ugly, though.)

Note that you can NOT use the binst pointer to access object B in A's constructor, because it's not fully constructed yet.

猛虎独行 2024-10-11 14:32:11

它实际上需要 binst 作为成员,还是只需要访问它?

class B;

class A {
public:
    B& binst(); //throws exception if not derived from B

    A() {}
    virtual ~A() {} //effectively required for the dynamic_cast
    void foo();
};

class B : public A {
public:
    void bar() {};
};

B& A::binst() {return dynamic_cast<B&>(this);} 
void A::foo() {return binst().bar();}

Does it actually need the binst as a member, or does it simply need to access it?

class B;

class A {
public:
    B& binst(); //throws exception if not derived from B

    A() {}
    virtual ~A() {} //effectively required for the dynamic_cast
    void foo();
};

class B : public A {
public:
    void bar() {};
};

B& A::binst() {return dynamic_cast<B&>(this);} 
void A::foo() {return binst().bar();}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文