Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 多态性++;参考资料_C++_Polymorphism_Reference - Fatal编程技术网

C++ 多态性++;参考资料

C++ 多态性++;参考资料,c++,polymorphism,reference,C++,Polymorphism,Reference,我想知道,相对于指针,如何使用引用实现多态性 要澄清,请参见以下示例: class A; class B { public: A& a; ///////////////// <- #1 B(); void doStuff(); }; class A { public: virtual void doSmth() = 0; }; void B::doStuff() { a.doSmth(); } class A1 : public A

我想知道,相对于指针,如何使用引用实现多态性

要澄清,请参见以下示例:

class A;

class B {
  public:
    A& a; ///////////////// <- #1
    B();
    void doStuff();
};

class A {
  public:
    virtual void doSmth() = 0;
};
void B::doStuff() {
  a.doSmth();
}

class A1 : public A {
  public:
    void doSmth() {
    }
};

B::B() : a(
    *        ////////////// <- #2
      (new A1)  /////////// <- #3
     ) {
}
A类;
B类{
公众:

A&A;///p>没有什么奇怪的。多态性适用于指针和引用:

struct Base { };
struct Derived : Base;

void foo(Base &);

int main() {
  Derived x;
  foo(x);    // fine
}
您将此问题与另一个问题混为一谈,即创建对动态对象的引用:

T * pt = new T;
T & rt = *pt;

T & x = *new T;  // same effect
请注意,仅通过引用跟踪动态对象通常是非常糟糕的样式,因为删除它的唯一方法是通过
delete&x;
,很难看出
x
需要清理

您的设计有两种直接的选择:1)在
B
中使
a
成为成员对象,或2)使
a
a
shared\u ptr
unique\u ptr
并将初始值更改为
a(新A1)
。这完全取决于您是否真正需要多态行为,也就是说,是否有其他
B
构造函数将不同的派生类分配给
a
,而不是
A1

不过,在这种情况下是否真的需要动态内存分配

动态内存分配或将引用注入B的ctor

不过,在这种情况下是否真的需要动态内存分配 案子

不,只需先定义A1,然后使其成为B的普通成员


多态性在引用和指针上都可以正常工作。

这确实有点奇怪。如果您想要类型为
A1
的成员变量(而不是引用),为什么不重新排列代码,使
A1
的定义出现在
B
的定义之前?

不难想象为什么引用可以像指针一样以多态方式工作(更不用说引用通常被实现为指针)。下面是一个快速示例:

class Base { 
public:
    virtual void something() { }
};

class Derived : public Base {
public:
    void something() { }
};

Base& foo() {
    static Derived d;
    return d;
}

foo().something(); // calls Derived's something

还有,为什么要为引用分配动态内存?在这种情况下,您可能根本不应该使用引用。此外,使用引用成员编写类可以有效地防止赋值(我听到有人说得很好)。

呃,这还不够吗

#include <iostream>

struct A;

struct B
{
  B(A& a);

  void foo();

  A& _a;
};

struct A
{
  virtual void foo() =0;
};

struct A1 : public A
{
  virtual void foo() { std::cout << "A1::foo" << std::endl; }
};

B::B(A& a) : _a(a) {}
void B::foo() { _a.foo(); }


int main(void)
{ 
  A1 a;  // instance of A1
  B b(a); // construct B with it

  b.foo();
}
#包括
结构A;
结构B
{
B(A&A);
void foo();
A和u A;
};
结构A
{
虚拟void foo()=0;
};
结构A1:公共A
{

virtual void foo(){std::cout我意识到这是一篇非常古老的文章,但对于处理动态分配对象的引用,您还有另一个选择。您可以为动态分配的对象分配一个引用。下面是一些虚拟代码,让您了解其工作原理

struct A
{
  int b;
  virtual void print();
  A(int val):b(val) {}
};

struct A_child:public A
{
  A_child(int val):A(val) {}
  void print();
};

void A:print()
{
cout<<"parent\n";
}

void A_child:print()
{
cout<<"child\n";
}

struct test_ref
{
A *& ref;
test_ref(A * ptr) : ref(ptr)
}

int main()
{

  test_ref parent(new A(12));
  parent.ref->print();

  test_ref child(new A_child(15));
  child.ref->print();
} 
结构A { int b; 虚拟空打印(); A(int-val):b(val){} }; 结构A_子项:公共A { A_child(int val):A(val){} 作废打印(); }; 作废A:print() {
为什么不只是修复问题,使
A1
的定义出现在
B
的定义之前?如果B总是使用A1,那么为什么不只是声明A1类型的对象而不是对a的引用?@Oli:减少依赖性?@Simon:我更喜欢处理依赖性,而不是处理对动态创建的对象的引用对象!@bitmask:我看不出编辑与依赖项有什么关系。没有任何进一步的信息,正确的答案(根据最佳实践)目前只是重新排列定义。最简单的方法是使用
A*const A
而不是
A&A
,但更糟糕的是,不可重置指针最好用引用来表示,不是吗?解决方案2):依赖关系……请记住,任何类型的资源持有成员都会给您的类更复杂的复制和分配语义。你必须决定这是否值得。依赖性可能会通过适当的前向声明来缓解,但前提是你选择指针解决方案(但你可能能够避免虚拟分派)。
B
实际上也是一个单例,
a
。这是否意味着“仅通过引用跟踪动态对象”不太糟糕的做法?不。在这种情况下,使用
唯一的\u ptr
,这是迄今为止最干净的PIMPL解决方案。您的类将不可复制,但那应该没问题。“不可重置指针最好通过引用来表示,不是吗?“当然不是。为什么任何指针都最好用引用来表示呢?它不是引用:它是指针。具体来说,是一个bog标准的
const
指针。请只使用
*const
,如果这样的话,任何人都可以阅读您的代码(包括未来的您)可以在语义上做出有用的猜测。不,创建
B
的人对如何创建
A1
实例知之甚少。但这并不能解决问题:/这是一件完全愚蠢和错误的事情。你正在引用一个函数局部变量,并将其存储到函数的作用域之外。这永远不会起作用。