首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >C++在if-else内部声明派生类对象并在外部使用它

C++在if-else内部声明派生类对象并在外部使用它
EN

Stack Overflow用户
提问于 2016-03-25 18:58:32
回答 6查看 243关注 0票数 1

我有一个名为Alma的(父)类,带有(虚拟)函数Getwidth()和两个派生类Alma,名为Birs (具有特殊函数Getheight())和Citrom (具有特殊函数Getdepth())。我想声明一个名为Attila的对象,它的类型是Birs还是Citrom,这取决于bool。稍后,我想使用通用函数Getwidth()和特殊函数(取决于前面提到的bool )。

我的(不工作的)代码:

代码语言:javascript
运行
复制
/*...*/
/*Classes*/
class Alma{
  public: virtual int Getwidth() = 0;
  /*ect...*/
}

class Birs: public Alma{
  int Getwidth(){return 1;}
  public: int Getheight(){return 2;}
  /*ect...*/
}

class Citrom: public Alma{
  int Getwidth(){return 3;}
  public: int Getdepth(){return 4;}
  /*ect...*/
}
/*...*/
/*Using them*/
void Useobjects(){

/*Create object depending on bool*/
  if(b00lvar){
    Birs Andor();
    std::cout<<Andor.Getwidth()<<" "<<Andor.Getheight()<<std::endl;
  }else{
    Citrom Andor();
    std::cout<<Andor.Getwidth()<<" "<<Andor.Getdepth()<<std::endl;
  }

/*Using the common part of object*/  
  std::cout<<Andor.Getwidth()<<std::endl;

/*Using the special part of object*/
  if(b00lvar){
    std::cout<<Andor.Getheight()<<std::endl;
  }else{
    std::cout<<Andor.Getdepth()<<std::endl;
  } 

/*ect...*/
}
EN

回答 6

Stack Overflow用户

发布于 2016-03-25 19:15:17

这是多态对象处理的一个典型案例。只要确保你熟悉这个概念以及指针和引用即可。

你需要的东西看起来像这样:

代码语言:javascript
运行
复制
Alma* Andor;

 if(b00lvar){
    Andor = new Birs();
    std::cout<<Andor->Getwidth()<<" "<<Andor->Getheight()<<std::endl;
  }else{
    Andor = new Citrom();  
    std::cout<<Andor->Getwidth()<<" "<<Andor->Getdepth()<<std::endl;
  }

接下来,使用dynamic_cast返回派生类型,最后,当然不要忘记删除对象。但首先要了解这些概念。

票数 1
EN

Stack Overflow用户

发布于 2016-03-25 19:06:26

您不能定义类型为this或that的单个对象,这取决于其他内容。C++不是这样工作的。C++是一种静态类型的语言。这意味着每个对象的类型都是在编译时确定的。其他语言,如Perl或Javascript,是动态类型的,其中对象的类型是在运行时确定的,单个对象可以在某一时刻是一件事,在另一件事上是另一件事。

但是C++不是这样工作的。

要做一些像你试图做的事情,你必须重构代码,并使用虚拟超类。如下所示:

代码语言:javascript
运行
复制
void UseObject(Alma &andor)
{
  /*Using the common part of object*/  
  std::cout<<andor.Getwidth()<<std::endl;

  /*Using the special part of object*/

  /* This part is your homework assignment */
}


void Useobjects(){

/*Create object depending on bool*/
  if(b00lvar){
    Birs andor;
    std::cout<<Andor.Getwidth()<<" "<<Andor.Getheight()<<std::endl;
    UseObject(andor);
  }else{
    Citrom andor;
    std::cout<<Andor.Getwidth()<<" "<<Andor.Getdepth()<<std::endl;
    UseObject(andor);
  }
}

另一种方法是使用两个指针,在本例中将两个指针传递给UseObject()。两个指针中的一个将始终是nullptr,另一个是指向实例化对象的指针,并将UseObject()编码为处理传入的任何对象。

这也是可能的,但会导致丑陋的代码,如果我是一名教授C++的教师,我会记下任何提交了这样做的代码的人。

票数 0
EN

Stack Overflow用户

发布于 2016-03-25 19:19:07

您可以使用指针语义来实现这一点,使用dynamic_cast来实现类型自省。我扩展了您的示例,以展示我将如何处理它。

这是Demo

代码语言:javascript
运行
复制
#include <iostream>
#include <memory>
using namespace std;

class Alma{
public:
    virtual int Getwidth() = 0;
};

class Birs: public Alma{
public:
    int Getwidth()  { return 1; }
    int Getheight() { return 2; }
};

class Citrom: public Alma{
public:
    int Getwidth() { return 3; }
    int Getdepth() { return 4; }
};

shared_ptr<Alma> make_attila(bool birs)
{
    if (birs)
        return make_shared<Birs>();
    else
        return make_shared<Citrom>();
}

void test_attila(shared_ptr<Alma> attila)
{
    cout << "width: " << attila->Getwidth() << "\n";
    if (auto as_birs = dynamic_pointer_cast<Birs>(attila))
        cout << "height: " << as_birs->Getheight() << "\n";
    else if (auto as_citrom = dynamic_pointer_cast<Citrom>(attila))
        cout << "depth: " << as_citrom->Getdepth() << "\n";
}

int main() {
    shared_ptr<Alma> attila = make_attila(true);
    test_attila(attila);
    attila = make_attila(false);
    test_attila(attila);
    return 0;
}

下一步是将make_attila作为模板函数,将派生类作为模板参数,而不是布尔值。

代码语言:javascript
运行
复制
template <class Derived>
shared_ptr<Alma> make_attila()
{
   return make_shared<Derived>();
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36218655

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档