【问题标题】:Is it possible declare a variable with different types in c++?是否可以在 C++ 中声明具有不同类型的变量?
【发布时间】:2011-09-16 02:47:54
【问题描述】:

我正在尝试像这样声明一个变量:

switch(foo){
    case 1:
        MyClass myObject();
        break;
    case 2:
        MyClass2 myObject();
        break;
    case 3:
        MyClass3 myObject();
        break;
}

但是在编译这个的时候,编译器会返回这些错误:

  • 跨过“MyClass myObject”的初始化
  • 冲突声明“MyClass2 myObject”
  • “myObject”之前的声明为“MyClass myObject”

有什么办法解决这个问题吗?

【问题讨论】:

  • 为什么要声明同名的对象?之后你将如何使用它们?似乎您需要将程序分成三种情况来以不同方式处理每个 myObject ——因此您似乎不需要为每个情况使用相同的名称。
  • 等等,我有没有听到有人说“抽象工厂模式”?

标签: c++ variables object initialization


【解决方案1】:

switch 语句的主体是单个作用域。如果你想声明一个局部于单个 case 的变量,你必须使用花括号在 case 中创建一个块:

switch (foo) {
  case 1: {
    MyClass myObject();
    break;
  }
  case 2: {
    MyClass2 myObject();
    break;
  }
  case 3: {
    MyClass3 myObject();
    break;
  }
}

如果您发现您经常这样做,您可以考虑为每个 case 中的代码创建函数,以获得更易于理解和维护的代码:

switch (foo) {
  case 1:
    HandleCase1();
    break;
  case 2:
    HandleCase2();
    break;
  case 3:
    HandleCase3();
    break;
}

【讨论】:

    【解决方案2】:

    不,你不能这样做。除了 switch 内部的命名冲突之外,你还有离开 switch 时变量超出范围的问题。

    最重要的是,MyClass myObject(); 声明了一个返回 MyClass 的函数。您可以将变量声明为 MyClass myObject;

    如果你需要三个不同的对象,也许你应该写三个不同的函数。或者可能是一个可以与不同类型一起使用的模板函数。

    【讨论】:

    • 我的问题的一个简单解决方案是创建一个模板函数,并为每个案例语句调用它。工厂解决方案是一个很好的方法,但没有这个(时间编码)那么快
    【解决方案3】:

    你想达到什么目的?如果您尝试声明一个变量并稍后使用它,那么:

    为此使用继承和工厂。

    ParentObject * FactoryCreator::createObject(cstring type){
       ParentObject * theObject = null;
       switch(type){
          case "type1":
              theObject = new ObjectType1();
              break;
          case "type2":
              theObject = new ObjectType2();
              break;
          ...
       }
       return theObject;
    }
    

    从你的代码中。

    ParentObject object = FactoryCreator::createObject("type you want");
    

    您必须创建一个结构,其中 ParentObject 是抽象的,并且所有类型的对象都继承自它。

    【讨论】:

    • 如果我使用工厂,这意味着修改模型,因为我正在测试一些外部证明的类。
    【解决方案4】:

    您可以查看 Bo Persson 告诉您的有关声明变量 here 的内容。我认为你想要做的是使用多态性。即使MyClass1MyClass2MyClass3 成为BaseClass 的派生对象,然后您可以执行以下操作:

    BaseClass *myObject;
    switch (foo) {
        case  1: {
            myObject = new MyClass1;
            break;
        }
       case  2: {
            myObject = new MyClass2; 
            break;
        }
        case  3: {
            myObject = new MyClass3;
            break;
        }
    }
    

    现在您可以让 myObject 的行为与您声明的对象一样,并且不仅可以在该 switch 语句的范围内使用。

    【讨论】:

    • 我不太记得myObject = new MyClass1 是正确的还是应该是myObject = new MyClass1()。无论如何,如果您对继承不太熟悉,您应该阅读此parashift.com/c++-faq-lite/basics-of-inheritance.html
    • 两者都是正确的。 new MyClass1 将使用默认初始化,new MyClass1() 将使用值初始化。对于类类型,这做同样的事情;存在差异,例如int 其中值初始化保证零初始化。
    【解决方案5】:

    您可以尝试boost::variant 并使用访问者:

    typedef boost::variant<MyClass1, MyClass2, MyClass3> MyVariantClass;
    
    boost::shared_ptr<MyVariantClass> myObject;
    switch (foo) {
        case  1: {
            MyClass1 object();
            myObject = boost::shared_ptr<MyVariantClass>(new MyVariantClass(object))
            break;
        }
       case  2: {
            MyClass2 object();
            myObject = boost::shared_ptr<MyVariantClass>(new MyVariantClass(object))
            break;
        }
        case  3: {
            MyClass3 object();
            myObject = boost::shared_ptr<MyVariantClass>(new MyVariantClass(object))
            break;
        }
    }
    

    然后创建一个访问者,就像助推人员在他们的教程中所说的那样。 这里唯一的问题是你真的创建了两个对象。声明中的对象本身(MyClass3 object()),然后是变体在内部进行的复制。

    【讨论】:

      猜你喜欢
      • 2018-05-02
      • 1970-01-01
      • 2019-01-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多