如何检查对象的类型是否是 C 中的特定子类?

发布于 2024-07-09 02:52:34 字数 72 浏览 6 评论 0原文

我正在考虑使用 typeid() 但我不知道如何询问该类型是否是另一个类的子类(顺便说一句,它是抽象的)

I was thinking along the lines of using typeid() but I don't know how to ask if that type is a subclass of another class (which, by the way, is abstract)

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

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

发布评论

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

评论(15

愿得七秒忆 2024-07-16 02:52:34

 

class Base
{
  public: virtual ~Base() {}
};

class D1: public Base {};

class D2: public Base {};

int main(int argc,char* argv[]);
{
  D1   d1;
  D2   d2;

  Base*  x = (argc > 2)?&d1:&d2;

  if (dynamic_cast<D2*>(x) == nullptr)
  {
    std::cout << "NOT A D2" << std::endl;
  }
  if (dynamic_cast<D1*>(x) == nullptr)
  {
    std::cout << "NOT A D1" << std::endl;
  }
}

 

class Base
{
  public: virtual ~Base() {}
};

class D1: public Base {};

class D2: public Base {};

int main(int argc,char* argv[]);
{
  D1   d1;
  D2   d2;

  Base*  x = (argc > 2)?&d1:&d2;

  if (dynamic_cast<D2*>(x) == nullptr)
  {
    std::cout << "NOT A D2" << std::endl;
  }
  if (dynamic_cast<D1*>(x) == nullptr)
  {
    std::cout << "NOT A D1" << std::endl;
  }
}
〆一缕阳光ご 2024-07-16 02:52:34

你真的不应该。 如果您的程序需要知道对象是什么类,这通常表明存在设计缺陷。 看看是否可以使用虚函数获得您想要的行为。 此外,有关您正在尝试做什么的更多信息也会有所帮助。

我假设你遇到这样的情况:

class Base;
class A : public Base {...};
class B : public Base {...};

void foo(Base *p)
{
  if(/* p is A */) /* do X */
  else /* do Y */
}

如果这就是你所遇到的情况,那么尝试做这样的事情:

class Base
{
  virtual void bar() = 0;
};

class A : public Base
{
  void bar() {/* do X */}
};

class B : public Base
{
  void bar() {/* do Y */}
};

void foo(Base *p)
{
  p->bar();
}

编辑:由于关于这个答案的争论在这么多年后仍然在继续,我想我应该添加一些参考资料。 如果您有一个指向基类的指针或引用,并且您的代码需要知道该对象的派生类,那么它违反了 里氏替换原则鲍勃叔叔 将此称为“面向对象设计的诅咒"。

You really shouldn't. If your program needs to know what class an object is, that usually indicates a design flaw. See if you can get the behavior you want using virtual functions. Also, more information about what you are trying to do would help.

I am assuming you have a situation like this:

class Base;
class A : public Base {...};
class B : public Base {...};

void foo(Base *p)
{
  if(/* p is A */) /* do X */
  else /* do Y */
}

If this is what you have, then try to do something like this:

class Base
{
  virtual void bar() = 0;
};

class A : public Base
{
  void bar() {/* do X */}
};

class B : public Base
{
  void bar() {/* do Y */}
};

void foo(Base *p)
{
  p->bar();
}

Edit: Since the debate about this answer still goes on after so many years, I thought I should throw in some references. If you have a pointer or reference to a base class, and your code needs to know the derived class of the object, then it violates Liskov substitution principle. Uncle Bob calls this an "anathema to Object Oriented Design".

谁的年少不轻狂 2024-07-16 02:52:34

您可以使用dynamic_cast(至少对于多态类型)来做到这一点。

实际上,再想一想,您无法通过 dynamic_cast 判断它是否是特定类型 - 但您可以判断它是否是该类型或其任何子类。

template <class DstType, class SrcType>
bool IsType(const SrcType* src)
{
  return dynamic_cast<const DstType*>(src) != nullptr;
}

You can do it with dynamic_cast (at least for polymorphic types).

Actually, on second thought--you can't tell if it is SPECIFICALLY a particular type with dynamic_cast--but you can tell if it is that type or any subclass thereof.

template <class DstType, class SrcType>
bool IsType(const SrcType* src)
{
  return dynamic_cast<const DstType*>(src) != nullptr;
}
静若繁花 2024-07-16 02:52:34

下面的代码演示了 3 种不同的实现方法:

  • virtual function
  • typeiddynamic_cast
  • 上面
#include <iostream>
#include <typeinfo>
#include <typeindex>

enum class Type {Base, A, B};

class Base {
public:
    virtual ~Base() = default;
    virtual Type type() const {
        return Type::Base;
    }
};

class A : public Base {
    Type type() const override {
        return Type::A;
    }
};

class B : public Base {
    Type type() const override {
        return Type::B;
    }
};

int main()
{
    const char *typemsg;
    A a;
    B b;
    Base *base = &a;             // = &b;    !!!!!!!!!!!!!!!!!
    Base &bbb = *base;

    // below you can replace    base    with  &bbb    and get the same results

    // USING virtual function
    // ======================
    // classes need to be in your control
    switch(base->type()) {
    case Type::A:
        typemsg = "type A";
        break;
    case Type::B:
        typemsg = "type B";
        break;
    default:
        typemsg = "unknown";
    }
    std::cout << typemsg << std::endl;

    // USING typeid
    // ======================
    // needs RTTI. under gcc, avoid -fno-rtti
    std::type_index ti(typeid(*base));
    if (ti == std::type_index(typeid(A))) {
        typemsg = "type A";
    } else if (ti == std::type_index(typeid(B))) {
        typemsg = "type B";
    } else {
        typemsg = "unknown";
    }
    std::cout << typemsg << std::endl;

    // USING dynamic_cast
    // ======================
    // needs RTTI. under gcc, avoid -fno-rtti
    if (dynamic_cast</*const*/ A*>(base)) {
        typemsg = "type A";
    } else if (dynamic_cast</*const*/ B*>(base)) {
        typemsg = "type B";
    } else {
        typemsg = "unknown";
    }
    std::cout << typemsg << std::endl;
}

的程序打印出以下内容:

type A
type A
type A

The code below demonstrates 3 different ways of doing it:

  • virtual function
  • typeid
  • dynamic_cast
#include <iostream>
#include <typeinfo>
#include <typeindex>

enum class Type {Base, A, B};

class Base {
public:
    virtual ~Base() = default;
    virtual Type type() const {
        return Type::Base;
    }
};

class A : public Base {
    Type type() const override {
        return Type::A;
    }
};

class B : public Base {
    Type type() const override {
        return Type::B;
    }
};

int main()
{
    const char *typemsg;
    A a;
    B b;
    Base *base = &a;             // = &b;    !!!!!!!!!!!!!!!!!
    Base &bbb = *base;

    // below you can replace    base    with  &bbb    and get the same results

    // USING virtual function
    // ======================
    // classes need to be in your control
    switch(base->type()) {
    case Type::A:
        typemsg = "type A";
        break;
    case Type::B:
        typemsg = "type B";
        break;
    default:
        typemsg = "unknown";
    }
    std::cout << typemsg << std::endl;

    // USING typeid
    // ======================
    // needs RTTI. under gcc, avoid -fno-rtti
    std::type_index ti(typeid(*base));
    if (ti == std::type_index(typeid(A))) {
        typemsg = "type A";
    } else if (ti == std::type_index(typeid(B))) {
        typemsg = "type B";
    } else {
        typemsg = "unknown";
    }
    std::cout << typemsg << std::endl;

    // USING dynamic_cast
    // ======================
    // needs RTTI. under gcc, avoid -fno-rtti
    if (dynamic_cast</*const*/ A*>(base)) {
        typemsg = "type A";
    } else if (dynamic_cast</*const*/ B*>(base)) {
        typemsg = "type B";
    } else {
        typemsg = "unknown";
    }
    std::cout << typemsg << std::endl;
}

The program above prints this:

type A
type A
type A
遗失的美好 2024-07-16 02:52:34

dynamic_cast 可以确定类型是否在继承层次结构中的任何位置包含目标类型(是的,这是一个鲜为人知的功能,如果 B 继承自 AC,它可以将A*直接变成C*)。 typeid()可以确定对象的确切类型。 然而,这些都应该非常谨慎地使用。 正如已经提到的,您应该始终避免动态类型识别,因为它表明了设计缺陷。 (此外,如果您确定该对象是目标类型,则可以使用 static_cast 进行向下转型。Boost 提供了 polymorphic_downcast ,它将使用 < code>dynamic_cast 和 assert 在调试模式下,在发布模式下它只会使用 static_cast)。

dynamic_cast can determine if the type contains the target type anywhere in the inheritance hierarchy (yes, it's a little-known feature that if B inherits from A and C, it can turn an A* directly into a C*). typeid() can determine the exact type of the object. However, these should both be used extremely sparingly. As has been mentioned already, you should always be avoiding dynamic type identification, because it indicates a design flaw. (also, if you know the object is for sure of the target type, you can do a downcast with a static_cast. Boost offers a polymorphic_downcast that will do a downcast with dynamic_cast and assert in debug mode, and in release mode it will just use a static_cast).

爱本泡沫多脆弱 2024-07-16 02:52:34

我不知道我是否正确理解你的问题,所以让我用自己的话重述一下......

问题:给定类 BD,确定是否 DB 的子类(反之亦然?)

解决方案:使用一些模板魔法! 好吧,说实话,您需要看看 LOKI,这是一个由著名的 C++ 作者 Andrei Alexandrescu 制作的出色的模板元编程库。

更具体地说,下载 LOKI 并包含标头 TypeManip .h ,然后在源代码中使用 SuperSubclass 类模板,如下所示:

if(SuperSubClass<B,D>::value)
{
...
}

根据文档,SuperSubClass::value 将是如果 BD 的公共基类,或者如果 BD 是同一类型的别名,则为 true。

DB 的子类,或者DB 相同。

我希望这有帮助。

编辑:

请注意,与某些使用dynamic_cast的方法不同,SuperSubClass::value 的评估发生在编译时,因此有在运行时使用该系统不会受到任何惩罚。

I don't know if I understand your problem correctly, so let me restate it in my own words...

Problem: Given classes B and D, determine if D is a subclass of B (or vice-versa?)

Solution: Use some template magic! Okay, seriously you need to take a look at LOKI, an excellent template meta-programming library produced by the fabled C++ author Andrei Alexandrescu.

More specifically, download LOKI and include header TypeManip.h from it in your source code then use the SuperSubclass class template as follows:

if(SuperSubClass<B,D>::value)
{
...
}

According to documentation, SuperSubClass<B,D>::value will be true if B is a public base of D, or if B and D are aliases of the same type.

i.e. either D is a subclass of B or D is the same as B.

I hope this helps.

edit:

Please note the evaluation of SuperSubClass<B,D>::value happens at compile time unlike some methods which use dynamic_cast, hence there is no penalty for using this system at runtime.

独守阴晴ぅ圆缺 2024-07-16 02:52:34

我不同意你永远不应该在 C++ 中检查对象的类型。 如果你能避免它,我同意你应该这样做。 不过,说在任何情况下都不应该这样做就太过分了。 您可以使用多种语言来完成此操作,这可以让您的生活变得更加轻松。 例如,Howard Pinsley 在他关于 C# 的文章中向我们展示了如何操作。

我使用 Qt 框架做了很多工作。 一般来说,我会模仿他们做事的方式(至少在他们的框架中工作时)。 QObject 类是所有 Qt 对象的基类。 该类具有 isWidgetType() 和 isWindowType() 函数作为快速子类检查。 那么为什么不能检查您自己的派生类,它在本质上是可比较的呢? 这是从其他一些帖子中衍生出来的 QObject:

class MyQObject : public QObject
{
public:
    MyQObject( QObject *parent = 0 ) : QObject( parent ){}
    ~MyQObject(){}

    static bool isThisType( const QObject *qObj )
    { return ( dynamic_cast<const MyQObject*>(qObj) != NULL ); }
};

然后,当您传递指向 QObject 的指针时,您可以通过调用静态成员函数来检查它是否指向您的派生类:

if( MyQObject::isThisType( qObjPtr ) ) qDebug() << "This is a MyQObject!";

I disagree that you should never want to check an object's type in C++. If you can avoid it, I agree that you should. Saying you should NEVER do this under any circumstance is going too far though. You can do this in a great many languages, and it can make your life a lot easier. Howard Pinsley, for instance, showed us how in his post on C#.

I do a lot of work with the Qt Framework. In general, I model what I do after the way they do things (at least when working in their framework). The QObject class is the base class of all Qt objects. That class has the functions isWidgetType() and isWindowType() as a quick subclass check. So why not be able to check your own derived classes, which is comparable in it's nature? Here is a QObject spin off of some of these other posts:

class MyQObject : public QObject
{
public:
    MyQObject( QObject *parent = 0 ) : QObject( parent ){}
    ~MyQObject(){}

    static bool isThisType( const QObject *qObj )
    { return ( dynamic_cast<const MyQObject*>(qObj) != NULL ); }
};

And then when you are passing around a pointer to a QObject, you can check if it points to your derived class by calling the static member function:

if( MyQObject::isThisType( qObjPtr ) ) qDebug() << "This is a MyQObject!";
差↓一点笑了 2024-07-16 02:52:34
#include <stdio.h>
#include <iostream.h>

class Base
{
  public: virtual ~Base() {}

  template<typename T>
  bool isA() {
    return (dynamic_cast<T*>(this) != NULL);
  }
};

class D1: public Base {};
class D2: public Base {};
class D22: public D2 {};

int main(int argc,char* argv[]);
{
  D1*   d1  = new D1();
  D2*   d2  = new D2();
  D22*  d22 = new D22();

  Base*  x = d22;

  if( x->isA<D22>() )
  {
    std::cout << "IS A D22" << std::endl;
  }
  if( x->isA<D2>() )
  {
    std::cout << "IS A D2" << std::endl;
  }
  if( x->isA<D1>() )
  {
    std::cout << "IS A D1" << std::endl;
  }
  if(x->isA<Base>() )
  {
    std::cout << "IS A Base" << std::endl;
  }
}

结果:

IS A D22
IS A D2
IS A Base
#include <stdio.h>
#include <iostream.h>

class Base
{
  public: virtual ~Base() {}

  template<typename T>
  bool isA() {
    return (dynamic_cast<T*>(this) != NULL);
  }
};

class D1: public Base {};
class D2: public Base {};
class D22: public D2 {};

int main(int argc,char* argv[]);
{
  D1*   d1  = new D1();
  D2*   d2  = new D2();
  D22*  d22 = new D22();

  Base*  x = d22;

  if( x->isA<D22>() )
  {
    std::cout << "IS A D22" << std::endl;
  }
  if( x->isA<D2>() )
  {
    std::cout << "IS A D2" << std::endl;
  }
  if( x->isA<D1>() )
  {
    std::cout << "IS A D1" << std::endl;
  }
  if(x->isA<Base>() )
  {
    std::cout << "IS A Base" << std::endl;
  }
}

Result:

IS A D22
IS A D2
IS A Base
十六岁半 2024-07-16 02:52:34

我正在考虑使用typeid()...

嗯,是的,可以通过比较来完成:typeid().name()。 如果我们采用已经描述的情况,其中:

class Base;
class A : public Base {...};
class B : public Base {...};

void foo(Base *p)
{
  if(/* p is A */) /* do X */
  else /* do Y */
}

foo(Base *p) 的可能实现将是:

#include <typeinfo>

void foo(Base *p)
{
    if(typeid(*p) == typeid(A))
    {
        // the pointer is pointing to the derived class A
    }  
    else if (typeid(*p).name() == typeid(B).name()) 
    {
        // the pointer is pointing to the derived class B
    }
}

I was thinking along the lines of using typeid()...

Well, yes, it could be done by comparing: typeid().name(). If we take the already described situation, where:

class Base;
class A : public Base {...};
class B : public Base {...};

void foo(Base *p)
{
  if(/* p is A */) /* do X */
  else /* do Y */
}

A possible implementation of foo(Base *p) would be:

#include <typeinfo>

void foo(Base *p)
{
    if(typeid(*p) == typeid(A))
    {
        // the pointer is pointing to the derived class A
    }  
    else if (typeid(*p).name() == typeid(B).name()) 
    {
        // the pointer is pointing to the derived class B
    }
}
恏ㄋ傷疤忘ㄋ疼 2024-07-16 02:52:34

我在这里看到了一些好的答案,也看到了一些愚蠢的答案。

“尝试查询对象的类型是一个设计缺陷”。 这意味着 Java instanceof 和 C# is 关键字是设计缺陷。 这些是不评价多态性的人的反应。 如果您有一个接口,则该接口是由另一个实现更多功能的接口派生的。 如果您需要这些额外的功能,您必须首先检查您是否有这样的接口。 甚至微软的 COM API 也使用了这种设计。

那么就如何推断一个对象是否是类的实例而言,已经给出了许多好的答案

  • typeid
  • 具有虚拟类型函数
  • 动态强制转换

is_base_of 与多态性无关。

让每个虚函数定义自己的类型方法是不必要的,因为它是多余的。 每个虚拟类已经有一个指向其虚拟表的指针。

class Base
{
 void *p_virtual_table = BASE_VIRTUAL_TABLE;
}

class Derived : Base
{
 void *p_virtual_table = DERIVED_VIRTUAL_TABLE;
}

void *BASE_VIRTUAL_TABLE[n];
void *DERIVED_VIRTUAL_TABLE[n];

这里的要点是,虚拟表的地址是固定的,简单的比较将决定虚拟对象是否是虚拟类的实例。

由于 cpp 没有为我们提供访问虚拟表的标准方法,因此很难手动进行这些比较。 但是 cpp 抽象机在推导虚拟对象的确切实例时绝对没有问题。

I see some good answers here and I see some dumb response.

"Trying to query the type of an object is a design flaw". Which means that Java instanceof and C# is keywords are design flaws. These are response of people that dont rate polymorphism. If you have an interface, that interface is derived by another interface that impelments more features. If you need these extra features you must first check that you have such an interface. Even microsoft COM API makes use of this design.

Then in terms of how to deduce if an object is a instanceof a class, many good answers have already been given

  • typeid
  • having a virtual type function
  • dynamic cast

is_base_of has nothing to do with polymorphism.

And having each virtual function define its own type method is unnecessary as it is redundant. Each virtual class already has a pointer to its virtual table.

class Base
{
 void *p_virtual_table = BASE_VIRTUAL_TABLE;
}

class Derived : Base
{
 void *p_virtual_table = DERIVED_VIRTUAL_TABLE;
}

void *BASE_VIRTUAL_TABLE[n];
void *DERIVED_VIRTUAL_TABLE[n];

The point here is that the address of the virtual tables are fixed and a simple comparrison will decide if a virtual object is an instanceof a virtual class.

Since cpp doesnt give us a standard way of accessing the virtual tables, it would be hard to do these comparrisons manually. But the cpp abstract machine has absolutely no problems deducing the exact instance of a virtual object.

神回复 2024-07-16 02:52:34

除非使用 RTTI,否则只能在编译时使用模板执行此操作。

它允许您使用 typeid 函数,该函数将生成一个指向 type_info 结构的指针,该结构包含有关类型的信息。

阅读维基百科

You can only do it at compile time using templates, unless you use RTTI.

It lets you use the typeid function which will yield a pointer to a type_info structure which contains information about the type.

Read up on it at Wikipedia

烏雲後面有陽光 2024-07-16 02:52:34

您可以使用模板(或SFINAE(替换失败不是错误))来完成此操作。 示例:

#include <iostream>

class base
{
public:
    virtual ~base() = default;
};

template <
    class type,
    class = decltype(
        static_cast<base*>(static_cast<type*>(0))
    )
>
bool check(type)
{
    return true;
}

bool check(...)
{
    return false;
}

class child : public base
{
public:
    virtual ~child() = default;
};

class grandchild : public child {};

int main()
{
    std::cout << std::boolalpha;

    std::cout << "base:       " << check(base())       << '\n';
    std::cout << "child:      " << check(child())      << '\n';
    std::cout << "grandchild: " << check(grandchild()) << '\n';
    std::cout << "int:        " << check(int())        << '\n';

    std::cout << std::flush;
}

输出:

base:       true
child:      true
grandchild: true
int:        false

You can do it with templates (or SFINAE (Substitution Failure Is Not An Error)). Example:

#include <iostream>

class base
{
public:
    virtual ~base() = default;
};

template <
    class type,
    class = decltype(
        static_cast<base*>(static_cast<type*>(0))
    )
>
bool check(type)
{
    return true;
}

bool check(...)
{
    return false;
}

class child : public base
{
public:
    virtual ~child() = default;
};

class grandchild : public child {};

int main()
{
    std::cout << std::boolalpha;

    std::cout << "base:       " << check(base())       << '\n';
    std::cout << "child:      " << check(child())      << '\n';
    std::cout << "grandchild: " << check(grandchild()) << '\n';
    std::cout << "int:        " << check(int())        << '\n';

    std::cout << std::flush;
}

Output:

base:       true
child:      true
grandchild: true
int:        false
昔日梦未散 2024-07-16 02:52:34

作为多个其他答案(包括我之前自己发布的答案!)的衍生,这里有一个可以提供帮助的宏:

#define isInstance( ptr, clazz ) (dynamic_cast<const clazz*>(ptr) != NULL)

As a spin off of multiple other answers (including one I previously posted myself!), here's a macro to help:

#define isInstance( ptr, clazz ) (dynamic_cast<const clazz*>(ptr) != NULL)
始于初秋 2024-07-16 02:52:34

我为指针和引用参数定义了 2 个宏。 如果您与一个版本一致,则可以注释掉另一个版本并将其重命名为INSTANCEOF

#include <iostream>


#define INSTANCEOF_REF(derivedType, baseREF) (dynamic_cast<derivedType*>(&baseREF) != nullptr)
#define INSTANCEOF_PTR(derivedType, basePTR) (dynamic_cast<derivedType*>(basePTR) != nullptr)

class Base {
public:
    virtual ~Base() {}
};

class Derived : public Base {
};

int main() {
    Derived derivedObj; 
    Base* baseptr = &derivedObj;

    if (INSTANCEOF_REF(Derived, derivedObj)) {
        std::cout << "derivedObj is an instance of Derived." << std::endl;
    } else {
        std::cout << "derivedObj is NOT an instance of Derived." << std::endl;
    }  
    if (INSTANCEOF_REF(Base, derivedObj)) {
        std::cout << "derivedObj is an instance of Base." << std::endl;
    } else {
        std::cout << "derivedObj is NOT an instance of Base." << std::endl;
    }  

    if (INSTANCEOF_PTR(Derived, baseptr)) {
        std::cout << "baseptr is an instance of Derived." << std::endl;
    } else {
        std::cout << "baseptr is NOT an instance of Derived." << std::endl;
    } 
    
    if (INSTANCEOF_PTR(Base, baseptr)) {
        std::cout << "baseptr is an instance of Base." << std::endl;
    } else {
        std::cout << "baseptr is NOT an instance of Base." << std::endl;
    }

    return 0;
}

======

derivedObj is an instance of Derived.
derivedObj is an instance of Base.
baseptr is an instance of Derived.
baseptr is an instance of Base.

I define 2 macros for pointer and reference params. If you're consistent with one version, you can comment out the other and re-name it as INSTANCEOF only.

#include <iostream>


#define INSTANCEOF_REF(derivedType, baseREF) (dynamic_cast<derivedType*>(&baseREF) != nullptr)
#define INSTANCEOF_PTR(derivedType, basePTR) (dynamic_cast<derivedType*>(basePTR) != nullptr)

class Base {
public:
    virtual ~Base() {}
};

class Derived : public Base {
};

int main() {
    Derived derivedObj; 
    Base* baseptr = &derivedObj;

    if (INSTANCEOF_REF(Derived, derivedObj)) {
        std::cout << "derivedObj is an instance of Derived." << std::endl;
    } else {
        std::cout << "derivedObj is NOT an instance of Derived." << std::endl;
    }  
    if (INSTANCEOF_REF(Base, derivedObj)) {
        std::cout << "derivedObj is an instance of Base." << std::endl;
    } else {
        std::cout << "derivedObj is NOT an instance of Base." << std::endl;
    }  

    if (INSTANCEOF_PTR(Derived, baseptr)) {
        std::cout << "baseptr is an instance of Derived." << std::endl;
    } else {
        std::cout << "baseptr is NOT an instance of Derived." << std::endl;
    } 
    
    if (INSTANCEOF_PTR(Base, baseptr)) {
        std::cout << "baseptr is an instance of Base." << std::endl;
    } else {
        std::cout << "baseptr is NOT an instance of Base." << std::endl;
    }

    return 0;
}

======

derivedObj is an instance of Derived.
derivedObj is an instance of Base.
baseptr is an instance of Derived.
baseptr is an instance of Base.
掩耳倾听 2024-07-16 02:52:34

在 C# 中你可以简单地说:

if (myObj is Car) {

}

In c# you can simply say:

if (myObj is Car) {

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文