如何将类传递给方法,并从基类检测继承者

how to pass class to method, and from base class detect inheritor?

本文关键字:基类 继承者 检测 方法      更新时间:2023-10-16

很难确切地解释我在这里想做什么,但是我有一个基类和两个继承这个基类的类。继承它的两个类都有自己独特的成员。我希望能够将两者都传递给一个方法,并让该方法检测它是哪个,然后访问它们的唯一成员。我不能假设只有两个类继承它,所以我正在寻找一个更通用的解决方案。

下面是我要做的一个例子:

#include <iostream>
class Base {
  public:
    int _type;
    Base() { }
};
class First : public Base {
  public:
    int _first_only;
    First() { }
};
class Second : public Base {
  public:
    int _second_only;
    Second() { }
};
void test (Base b) {
  std::cout << "Type: " << b._type << std::endl;
  if(b._type==1) {
    std::cout << "Firstn";
    // Want to be able to do this
    std::cout << "Val: " << (First)b._first_only << std::endl; 
  } else if(b._type==2) {
    std::cout << "Secondn";
    // And this
    std::cout << "Val: " << (Second)b._second_only << std::endl;
  }
}
int main() {
  First f;
  f._first_only=1;
  f._type=1;
  Second s;
  s._type=2;
  s._second_only=2;
  test(f);
  test(s);
}

这与其他答案相似:

  1. 你可以编写多态类来使用虚函数获得这种行为
  2. 通过指针或引用传递派生类对象以获得多态行为。否则会导致对象切片。你的test()函数导致对象切片。

这段代码也可以帮助你。您可以看到有不同的打印方式。我使用了GetBaseType(), GetDerivedType()和GetType()。其中GetType()方法最适合您的情况。为方便起见,这里有两个构造函数。构造函数允许初始化数据成员。

class Base {
private:
    int _type;
public:
    Base(int type) : _type(type) { }
    int GetBaseType() { return _type; }
    virtual int GetDerivedType() = 0;
    virtual int GetType() { return _type; }
};
class First : public Base {
private:
    int _first_only;
public:
    First() : Base(1), _first_only(1) { }
    First(int first_only) : Base(first_only), _first_only(first_only) { }
    int GetDerivedType() { return _first_only; }
    virtual int GetType() { return _first_only; }
};
class Second : public Base {
private:
    int _second_only;
public:
    Second() : Base(2), _second_only(2) { }
    Second(int second_only) : Base(second_only), _second_only(second_only) { }
    int GetDerivedType() { return _second_only; }
    virtual int GetType() { return _second_only; }
};
void test (Base &b) {
    std::cout << "Type: " << b.GetBaseType() << std::endl;
    std::cout << "Type: " << b.Base::GetType() << std::endl;
    std::cout << "Dervied type: n";
    std::cout << "Val: " << b.GetDerivedType() << std::endl; 
    std::cout << "Val: " << b.GetType() << std::endl; 
}
int main() {
  First f(1);
  Second s(2);
  test(f);
  test(s);
  First f1;
  Second s1;
  test(f1);
  test(s1);
}
  1. Base
  2. 中声明virtual函数
  3. FirstSecond的常见成员类型移至Base

对于您的具体问题,第二个选项更好:

class Base {
  public:
    int _member;  // have getter() method, if '_member' is private
    Base() { }
};

Inside, test():

void test (Base &b) {  // <--- practice to pass by reference if copy is not needed
  // use b._member;
};

你的代码不能多态工作,因为你是按值传递函数参数,这会导致切片。

如果你有一个方法对不同的类型做不同的事情,考虑为每一种类型重载它

我会做的三件事:

  • 一般来说,切换类型代码不被认为是好的面向对象设计:而是将切换后的代码拉入类中。
  • 我还在特定类的构造函数中设置了类型标记。
  • 正如其他人提到的,你需要通过引用传递参数,以避免切片。
下面是代码的样子:
#include <iostream>
class Base {
  public:
     int _type;
     Base() { }
     virtual void print_to_stream( std::ostream & os ) const =0;
};
class First : public Base {
  public:
    int _first_only;
    First() {  _type =1; }
    void print_to_stream( std::ostream & os ) const
    {
       os<<"Firstn";
       os<<"Val: " << _first_only << std::endl;
    }
};
class Second : public Base {
  public:
    int _second_only;
    Second() { _type=2; }
    void print_to_stream( std::ostream & os ) const
    {
      os << "Secondn";
      os << "Val: " << _second_only << std::endl;
    }
};
void test (Base & b)
{
  std::cout << "Type: " << b._type << std::endl;
  b.print_to_stream( std::cout );
}
int main() {
  First f;
  f._first_only=1;
  Second s;
  s._second_only=2;
  test(f);
  test(s);
}