C ++ tương đương với thể hiện của java


202

Phương pháp ưa thích để đạt được C ++ tương đương với java là instanceofgì?


57
Được ưa thích bởi hiệu suất và khả năng tương thích ...
Yuval Adam

7
không công bằng khi hỏi "instanceof - bằng ngôn ngữ nào?"
huyền bí

3
@mysticcoder: Tôi nhận được "например на" cho tiếng Bulgaria, GT không hỗ trợ C ++ mặc dù
Mark K Cowan

Câu trả lời:


200

Hãy thử sử dụng:

if(NewType* v = dynamic_cast<NewType*>(old)) {
   // old was safely casted to NewType
   v->doSomething();
}

Điều này đòi hỏi trình biên dịch của bạn phải kích hoạt hỗ trợ rtti.

EDIT: Tôi đã có một số ý kiến ​​tốt về câu trả lời này!

Mỗi khi bạn cần sử dụng một Dynamic_cast (hoặc thể hiện), bạn nên tự hỏi mình xem đó có phải là điều cần thiết không. Nó thường là một dấu hiệu của thiết kế kém.

Cách giải quyết điển hình là đưa hành vi đặc biệt cho lớp bạn đang kiểm tra vào một hàm ảo trên lớp cơ sở hoặc có thể giới thiệu một cái gì đó giống như khách truy cập nơi bạn có thể giới thiệu hành vi cụ thể cho các lớp con mà không thay đổi giao diện (ngoại trừ thêm giao diện chấp nhận của khách truy cập khóa học).

Như đã chỉ ra Dynamic_cast không miễn phí. Một hack đơn giản và thực hiện nhất quán xử lý hầu hết (nhưng không phải tất cả các trường hợp) về cơ bản là thêm một enum đại diện cho tất cả các loại có thể mà lớp của bạn có thể có và kiểm tra xem bạn có chọn đúng không.

if(old->getType() == BOX) {
   Box* box = static_cast<Box*>(old);
   // Do something box specific
}

Đây không phải là thiết kế oo tốt, nhưng nó có thể là một cách giải quyết và chi phí của nó ít nhiều chỉ bằng một cuộc gọi chức năng ảo. Nó cũng hoạt động bất kể RTTI có được kích hoạt hay không.

Lưu ý rằng phương pháp này không hỗ trợ nhiều cấp thừa kế, vì vậy nếu bạn không cẩn thận, bạn có thể kết thúc bằng mã trông như thế này:

// Here we have a SpecialBox class that inherits Box, since it has its own type
// we must check for both BOX or SPECIAL_BOX
if(old->getType() == BOX || old->getType() == SPECIAL_BOX) {
   Box* box = static_cast<Box*>(old);
   // Do something box specific
}

4
Đó thường là trường hợp khi bạn thực hiện kiểm tra "ví dụ"
Laserallan

7
Nếu bạn phải sử dụng instanceof, trong hầu hết các trường hợp, có điều gì đó không đúng với thiết kế của bạn.
mslot

24
Đừng quên rằng Dynamic_cast là một hoạt động với chi phí lớn.
Klaim

13
Có nhiều ví dụ về sử dụng hợp lý của thử nghiệm loại động. Nó thường không được ưa thích, nhưng nó có một vị trí. (Mặt khác, tại sao nó hoặc tương đương của nó xuất hiện trong mọi ngôn ngữ OO chính: C ++, Java, Python, v.v.?)
Paul Draper

2
Tôi sẽ bắt cả hai ở cấp IOException nếu chúng không cần phải xử lý khác nhau. Nếu chúng cần được xử lý khác nhau, thì tôi sẽ thêm một khối bắt cho mỗi ngoại lệ.
mslot

37

Tùy thuộc vào những gì bạn muốn làm, bạn có thể làm điều này:

template<typename Base, typename T>
inline bool instanceof(const T*) {
    return std::is_base_of<Base, T>::value;
}

Sử dụng:

if (instanceof<BaseClass>(ptr)) { ... }

Tuy nhiên, điều này hoàn toàn hoạt động trên các loại như trình biên dịch đã biết.

Biên tập:

Mã này sẽ làm việc cho các con trỏ đa hình:

template<typename Base, typename T>
inline bool instanceof(const T *ptr) {
    return dynamic_cast<const Base*>(ptr) != nullptr;
}

Ví dụ: http://cpp.sh/6qir


Giải pháp thanh lịch và được thực hiện tốt. +1 Nhưng hãy cẩn thận để có được con trỏ chính xác. Không hợp lệ cho con trỏ đa hình?
Adrian Maire

Điều gì xảy ra nếu chúng ta trì hoãn con trỏ khi sử dụng chức năng này? Sau đó nó sẽ làm việc cho con trỏ đa hình?
mark.kedzierski

Không có điều này chỉ hoạt động trên các loại như trình biên dịch đã biết. Không làm việc với con trỏ đa hình, bất kể bạn có nhận ra hay không. Tôi sẽ thêm một cái gì đó có thể làm việc trong trường hợp đó mặc dù.
panzi

2
Tôi đã sửa đổi ví dụ của bạn để viết phiên bản của phương thức này sử dụng tài liệu tham khảo thay vì con trỏ: cpp.sh/8owv
Sri Harsha Chilakapati

Tại sao loại mục tiêu của diễn viên động "const"?
dùng1056903

7

Triển khai Instanceof mà không có Dynamic_cast

Tôi nghĩ rằng câu hỏi này vẫn còn liên quan đến ngày hôm nay. Sử dụng tiêu chuẩn C ++ 11, giờ đây bạn có thể thực hiện một instanceofchức năng mà không cần sử dụng dynamic_castnhư thế này:

if (dynamic_cast<B*>(aPtr) != nullptr) {
  // aPtr is instance of B
} else {
  // aPtr is NOT instance of B
}

Nhưng bạn vẫn phụ thuộc vào RTTIhỗ trợ. Vì vậy, đây là giải pháp của tôi cho vấn đề này tùy thuộc vào một số Macros và Metaprogramming Magic. Hạn chế duy nhất imho là cách tiếp cận này không hoạt động cho nhiều kế thừa .

InstanceOfMacros.h

#include <set>
#include <tuple>
#include <typeindex>

#define _EMPTY_BASE_TYPE_DECL() using BaseTypes = std::tuple<>;
#define _BASE_TYPE_DECL(Class, BaseClass) \
  using BaseTypes = decltype(std::tuple_cat(std::tuple<BaseClass>(), Class::BaseTypes()));
#define _INSTANCE_OF_DECL_BODY(Class)                                 \
  static const std::set<std::type_index> baseTypeContainer;           \
  virtual bool instanceOfHelper(const std::type_index &_tidx) {       \
    if (std::type_index(typeid(ThisType)) == _tidx) return true;      \
    if (std::tuple_size<BaseTypes>::value == 0) return false;         \
    return baseTypeContainer.find(_tidx) != baseTypeContainer.end();  \
  }                                                                   \
  template <typename... T>                                            \
  static std::set<std::type_index> getTypeIndexes(std::tuple<T...>) { \
    return std::set<std::type_index>{std::type_index(typeid(T))...};  \
  }

#define INSTANCE_OF_SUB_DECL(Class, BaseClass) \
 protected:                                    \
  using ThisType = Class;                      \
  _BASE_TYPE_DECL(Class, BaseClass)            \
  _INSTANCE_OF_DECL_BODY(Class)

#define INSTANCE_OF_BASE_DECL(Class)                                                    \
 protected:                                                                             \
  using ThisType = Class;                                                               \
  _EMPTY_BASE_TYPE_DECL()                                                               \
  _INSTANCE_OF_DECL_BODY(Class)                                                         \
 public:                                                                                \
  template <typename Of>                                                                \
  typename std::enable_if<std::is_base_of<Class, Of>::value, bool>::type instanceOf() { \
    return instanceOfHelper(std::type_index(typeid(Of)));                               \
  }

#define INSTANCE_OF_IMPL(Class) \
  const std::set<std::type_index> Class::baseTypeContainer = Class::getTypeIndexes(Class::BaseTypes());

Bản giới thiệu

Sau đó, bạn có thể sử dụng công cụ này ( một cách thận trọng ) như sau:

DemoClassHVELy.hpp *

#include "InstanceOfMacros.h"

struct A {
  virtual ~A() {}
  INSTANCE_OF_BASE_DECL(A)
};
INSTANCE_OF_IMPL(A)

struct B : public A {
  virtual ~B() {}
  INSTANCE_OF_SUB_DECL(B, A)
};
INSTANCE_OF_IMPL(B)

struct C : public A {
  virtual ~C() {}
  INSTANCE_OF_SUB_DECL(C, A)
};
INSTANCE_OF_IMPL(C)

struct D : public C {
  virtual ~D() {}
  INSTANCE_OF_SUB_DECL(D, C)
};
INSTANCE_OF_IMPL(D)

Đoạn mã sau trình bày một bản demo nhỏ để xác minh hành vi thô sơ.

InstanceOfDemo.cpp

#include <iostream>
#include <memory>
#include "DemoClassHierarchy.hpp"

int main() {
  A *a2aPtr = new A;
  A *a2bPtr = new B;
  std::shared_ptr<A> a2cPtr(new C);
  C *c2dPtr = new D;
  std::unique_ptr<A> a2dPtr(new D);

  std::cout << "a2aPtr->instanceOf<A>(): expected=1, value=" << a2aPtr->instanceOf<A>() << std::endl;
  std::cout << "a2aPtr->instanceOf<B>(): expected=0, value=" << a2aPtr->instanceOf<B>() << std::endl;
  std::cout << "a2aPtr->instanceOf<C>(): expected=0, value=" << a2aPtr->instanceOf<C>() << std::endl;
  std::cout << "a2aPtr->instanceOf<D>(): expected=0, value=" << a2aPtr->instanceOf<D>() << std::endl;
  std::cout << std::endl;
  std::cout << "a2bPtr->instanceOf<A>(): expected=1, value=" << a2bPtr->instanceOf<A>() << std::endl;
  std::cout << "a2bPtr->instanceOf<B>(): expected=1, value=" << a2bPtr->instanceOf<B>() << std::endl;
  std::cout << "a2bPtr->instanceOf<C>(): expected=0, value=" << a2bPtr->instanceOf<C>() << std::endl;
  std::cout << "a2bPtr->instanceOf<D>(): expected=0, value=" << a2bPtr->instanceOf<D>() << std::endl;
  std::cout << std::endl;
  std::cout << "a2cPtr->instanceOf<A>(): expected=1, value=" << a2cPtr->instanceOf<A>() << std::endl;
  std::cout << "a2cPtr->instanceOf<B>(): expected=0, value=" << a2cPtr->instanceOf<B>() << std::endl;
  std::cout << "a2cPtr->instanceOf<C>(): expected=1, value=" << a2cPtr->instanceOf<C>() << std::endl;
  std::cout << "a2cPtr->instanceOf<D>(): expected=0, value=" << a2cPtr->instanceOf<D>() << std::endl;
  std::cout << std::endl;
  std::cout << "c2dPtr->instanceOf<A>(): expected=1, value=" << c2dPtr->instanceOf<A>() << std::endl;
  std::cout << "c2dPtr->instanceOf<B>(): expected=0, value=" << c2dPtr->instanceOf<B>() << std::endl;
  std::cout << "c2dPtr->instanceOf<C>(): expected=1, value=" << c2dPtr->instanceOf<C>() << std::endl;
  std::cout << "c2dPtr->instanceOf<D>(): expected=1, value=" << c2dPtr->instanceOf<D>() << std::endl;
  std::cout << std::endl;
  std::cout << "a2dPtr->instanceOf<A>(): expected=1, value=" << a2dPtr->instanceOf<A>() << std::endl;
  std::cout << "a2dPtr->instanceOf<B>(): expected=0, value=" << a2dPtr->instanceOf<B>() << std::endl;
  std::cout << "a2dPtr->instanceOf<C>(): expected=1, value=" << a2dPtr->instanceOf<C>() << std::endl;
  std::cout << "a2dPtr->instanceOf<D>(): expected=1, value=" << a2dPtr->instanceOf<D>() << std::endl;

  delete a2aPtr;
  delete a2bPtr;
  delete c2dPtr;

  return 0;
}

Đầu ra:

a2aPtr->instanceOf<A>(): expected=1, value=1
a2aPtr->instanceOf<B>(): expected=0, value=0
a2aPtr->instanceOf<C>(): expected=0, value=0
a2aPtr->instanceOf<D>(): expected=0, value=0

a2bPtr->instanceOf<A>(): expected=1, value=1
a2bPtr->instanceOf<B>(): expected=1, value=1
a2bPtr->instanceOf<C>(): expected=0, value=0
a2bPtr->instanceOf<D>(): expected=0, value=0

a2cPtr->instanceOf<A>(): expected=1, value=1
a2cPtr->instanceOf<B>(): expected=0, value=0
a2cPtr->instanceOf<C>(): expected=1, value=1
a2cPtr->instanceOf<D>(): expected=0, value=0

c2dPtr->instanceOf<A>(): expected=1, value=1
c2dPtr->instanceOf<B>(): expected=0, value=0
c2dPtr->instanceOf<C>(): expected=1, value=1
c2dPtr->instanceOf<D>(): expected=1, value=1

a2dPtr->instanceOf<A>(): expected=1, value=1
a2dPtr->instanceOf<B>(): expected=0, value=0
a2dPtr->instanceOf<C>(): expected=1, value=1
a2dPtr->instanceOf<D>(): expected=1, value=1

Hiệu suất

Câu hỏi thú vị nhất hiện nay là, nếu thứ xấu xa này hiệu quả hơn việc sử dụng dynamic_cast. Do đó, tôi đã viết một ứng dụng đo lường hiệu suất rất cơ bản.

InstanceOfPerformance.cpp

#include <chrono>
#include <iostream>
#include <string>
#include "DemoClassHierarchy.hpp"

template <typename Base, typename Derived, typename Duration>
Duration instanceOfMeasurement(unsigned _loopCycles) {
  auto start = std::chrono::high_resolution_clock::now();
  volatile bool isInstanceOf = false;
  for (unsigned i = 0; i < _loopCycles; ++i) {
    Base *ptr = new Derived;
    isInstanceOf = ptr->template instanceOf<Derived>();
    delete ptr;
  }
  auto end = std::chrono::high_resolution_clock::now();
  return std::chrono::duration_cast<Duration>(end - start);
}

template <typename Base, typename Derived, typename Duration>
Duration dynamicCastMeasurement(unsigned _loopCycles) {
  auto start = std::chrono::high_resolution_clock::now();
  volatile bool isInstanceOf = false;
  for (unsigned i = 0; i < _loopCycles; ++i) {
    Base *ptr = new Derived;
    isInstanceOf = dynamic_cast<Derived *>(ptr) != nullptr;
    delete ptr;
  }
  auto end = std::chrono::high_resolution_clock::now();
  return std::chrono::duration_cast<Duration>(end - start);
}

int main() {
  unsigned testCycles = 10000000;
  std::string unit = " us";
  using DType = std::chrono::microseconds;

  std::cout << "InstanceOf performance(A->D)  : " << instanceOfMeasurement<A, D, DType>(testCycles).count() << unit
            << std::endl;
  std::cout << "InstanceOf performance(A->C)  : " << instanceOfMeasurement<A, C, DType>(testCycles).count() << unit
            << std::endl;
  std::cout << "InstanceOf performance(A->B)  : " << instanceOfMeasurement<A, B, DType>(testCycles).count() << unit
            << std::endl;
  std::cout << "InstanceOf performance(A->A)  : " << instanceOfMeasurement<A, A, DType>(testCycles).count() << unit
            << "\n"
            << std::endl;
  std::cout << "DynamicCast performance(A->D) : " << dynamicCastMeasurement<A, D, DType>(testCycles).count() << unit
            << std::endl;
  std::cout << "DynamicCast performance(A->C) : " << dynamicCastMeasurement<A, C, DType>(testCycles).count() << unit
            << std::endl;
  std::cout << "DynamicCast performance(A->B) : " << dynamicCastMeasurement<A, B, DType>(testCycles).count() << unit
            << std::endl;
  std::cout << "DynamicCast performance(A->A) : " << dynamicCastMeasurement<A, A, DType>(testCycles).count() << unit
            << "\n"
            << std::endl;
  return 0;
}

Các kết quả khác nhau và về cơ bản dựa trên mức độ tối ưu hóa trình biên dịch. Biên dịch chương trình đo hiệu suất bằng cách sử dụng g++ -std=c++11 -O0 -o instanceof-performance InstanceOfPerformance.cppđầu ra trên máy cục bộ của tôi là:

InstanceOf performance(A->D)  : 699638 us
InstanceOf performance(A->C)  : 642157 us
InstanceOf performance(A->B)  : 671399 us
InstanceOf performance(A->A)  : 626193 us

DynamicCast performance(A->D) : 754937 us
DynamicCast performance(A->C) : 706766 us
DynamicCast performance(A->B) : 751353 us
DynamicCast performance(A->A) : 676853 us

Mhm, kết quả này rất tỉnh táo, bởi vì thời gian chứng minh rằng cách tiếp cận mới không nhanh hơn nhiều so với dynamic_castcách tiếp cận. Nó thậm chí còn kém hiệu quả hơn đối với trường hợp thử nghiệm đặc biệt sẽ kiểm tra xem một con trỏ của Alà một thể hiện của A. NHƯNG thủy triều xoay bằng cách điều chỉnh nhị phân của chúng tôi bằng cách sử dụng otpimization trình biên dịch. Lệnh biên dịch tương ứng là g++ -std=c++11 -O3 -o instanceof-performance InstanceOfPerformance.cpp. Kết quả trên máy cục bộ của tôi thật tuyệt vời:

InstanceOf performance(A->D)  : 3035 us
InstanceOf performance(A->C)  : 5030 us
InstanceOf performance(A->B)  : 5250 us
InstanceOf performance(A->A)  : 3021 us

DynamicCast performance(A->D) : 666903 us
DynamicCast performance(A->C) : 698567 us
DynamicCast performance(A->B) : 727368 us
DynamicCast performance(A->A) : 3098 us

Nếu bạn không phụ thuộc vào nhiều kế thừa, không phải là đối thủ của các macro C, RTTI và siêu lập trình mẫu cũ và không quá lười biếng để thêm một số hướng dẫn nhỏ vào các lớp của hệ thống phân cấp lớp của bạn, thì cách tiếp cận này có thể tăng cường ứng dụng của bạn một chút đối với hiệu suất của nó, nếu bạn thường kết thúc bằng việc kiểm tra thể hiện của một con trỏ. Nhưng sử dụng nó một cách thận trọng . Không có bảo hành cho tính chính xác của phương pháp này.

Lưu ý: Tất cả các bản demo được biên dịch bằng clang (Apple LLVM version 9.0.0 (clang-900.0.39.2))macOS Sierra trên MacBook Pro Mid 2012.

Chỉnh sửa: Tôi cũng đã kiểm tra hiệu năng trên máy Linux bằng cách sử dụng gcc (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609. Trên nền tảng này, lợi ích của nước hoa không quá quan trọng như trên macOs với tiếng kêu.

Đầu ra (không có tối ưu hóa trình biên dịch):

InstanceOf performance(A->D)  : 390768 us
InstanceOf performance(A->C)  : 333994 us
InstanceOf performance(A->B)  : 334596 us
InstanceOf performance(A->A)  : 300959 us

DynamicCast performance(A->D) : 331942 us
DynamicCast performance(A->C) : 303715 us
DynamicCast performance(A->B) : 400262 us
DynamicCast performance(A->A) : 324942 us

Đầu ra (với tối ưu hóa trình biên dịch):

InstanceOf performance(A->D)  : 209501 us
InstanceOf performance(A->C)  : 208727 us
InstanceOf performance(A->B)  : 207815 us
InstanceOf performance(A->A)  : 197953 us

DynamicCast performance(A->D) : 259417 us
DynamicCast performance(A->C) : 256203 us
DynamicCast performance(A->B) : 261202 us
DynamicCast performance(A->A) : 193535 us

Câu trả lời chu đáo! Tôi rất vui vì bạn đã cung cấp thời gian. Đây là một bài đọc thú vị.
Eric

0

dynamic_castđược biết là không hiệu quả. Nó truyền qua hệ thống phân cấp thừa kế và giải pháp duy nhất nếu bạn có nhiều cấp kế thừa và cần kiểm tra xem một đối tượng có phải là một thể hiện của bất kỳ một trong các loại trong phân cấp loại của nó không.

Nhưng nếu một dạng hạn chế hơn instanceofchỉ kiểm tra xem một đối tượng có chính xác là loại bạn chỉ định, đủ cho nhu cầu của bạn hay không, thì chức năng dưới đây sẽ hiệu quả hơn rất nhiều:

template<typename T, typename K>
inline bool isType(const K &k) {
    return typeid(T).hash_code() == typeid(k).hash_code();
}

Đây là một ví dụ về cách bạn gọi hàm trên:

DerivedA k;
Base *p = &k;

cout << boolalpha << isType<DerivedA>(*p) << endl;  // true
cout << boolalpha << isType<DerivedB>(*p) << endl;  // false

Bạn sẽ chỉ định loại mẫu A(như loại bạn đang kiểm tra) và chuyển vào đối tượng bạn muốn kiểm tra làm đối số (từ đó loại mẫu Ksẽ được suy ra).


Tiêu chuẩn không yêu cầu hash_code là duy nhất cho các loại khác nhau, vì vậy điều này không đáng tin cậy.
mattnz

2
Không phải bản thân (T) có thể so sánh được với sự bình đẳng, vì vậy không cần sự phụ thuộc vào mã băm?
Paul Stelian

-5
#include <iostream.h>
#include<typeinfo.h>

template<class T>
void fun(T a)
{
  if(typeid(T) == typeid(int))
  {
     //Do something
     cout<<"int";
  }
  else if(typeid(T) == typeid(float))
  {
     //Do Something else
     cout<<"float";
  }
}

void main()
 {
      fun(23);
      fun(90.67f);
 }

1
Đây là một ví dụ thực sự xấu. Tại sao không sử dụng quá tải, đó là rẻ hơn?
user1095108

11
Vấn đề chính là nó không trả lời được câu hỏi. instanceoftruy vấn kiểu động, nhưng trong câu trả lời này, kiểu động và tĩnh luôn tương ứng.
MSalters

@HHH bạn trả lời là cách thoát khỏi câu hỏi đang được hỏi!
lập trình viên

-11

Điều này hoạt động hoàn hảo đối với tôi khi sử dụng Code :: Blocks IDE với trình biên dịch GCC

#include<iostream>
#include<typeinfo>
#include<iomanip>
#define SIZE 20
using namespace std;

class Publication
{
protected:
    char title[SIZE];
    int price;

public:
    Publication()
    {
        cout<<endl<<" Enter title of media : ";
        cin>>title;

        cout<<endl<<" Enter price of media : ";
        cin>>price;
    }

    virtual void show()=0;
};

class Book : public Publication
{
    int pages;

public:
    Book()
    {
        cout<<endl<<" Enter number of pages : ";
        cin>>pages;
    }

    void show()
    {
        cout<<endl<<setw(12)<<left<<" Book Title"<<": "<<title;
        cout<<endl<<setw(12)<<left<<" Price"<<": "<<price;
        cout<<endl<<setw(12)<<left<<" Pages"<<": "<<pages;
        cout<<endl<<" ----------------------------------------";
    }
};

class Tape : public Publication
{
    int duration;

public:
    Tape()
    {
        cout<<endl<<" Enter duration in minute : ";
        cin>>duration;
    }

    void show()
    {
        cout<<endl<<setw(10)<<left<<" Tape Title"<<": "<<title;
        cout<<endl<<setw(10)<<left<<" Price"<<": "<<price;
        cout<<endl<<setw(10)<<left<<" Duration"<<": "<<duration<<" minutes";
        cout<<endl<<" ----------------------------------------";
    }
};
int main()
{
    int n, i, type;

    cout<<endl<<" Enter number of media : ";
    cin>>n;

    Publication **p = new Publication*[n];
    cout<<endl<<" Enter "<<n<<" media details : ";

    for(i=0;i<n;i++)
    {
        cout<<endl<<" Select Media Type [ 1 - Book / 2 - Tape ] ";
        cin>>type;

        if ( type == 1 )
        {
            p[i] = new Book();
        }
        else
        if ( type == 2 )
        {
            p[i] = new Tape();
        }
        else
        {
            i--;
            cout<<endl<<" Invalid type. You have to Re-enter choice";
        }
    }

    for(i=0;i<n;i++)
    {
        if ( typeid(Book) == typeid(*p[i]) )
        {
            p[i]->show();
        }
    }

    return 0;
}

1
@programmer Tôi nghĩ bạn muốn gọi @pgp, tôi chỉ đơn giản là sửa định dạng mã của anh ấy. Ngoài ra, câu trả lời của anh ta về cơ bản là "sử dụng typeid", trong khi sai ("Không có gì đảm bảo rằng cùng một trường hợp std :: type_info sẽ được tham chiếu bởi tất cả các đánh giá của biểu thức typeid trên cùng loại ... assert(typeid(A) == typeid(A)); /* not guaranteed */", xem cppreference.com ), không chỉ ra rằng anh ta ít nhất đã cố gắng trả lời câu hỏi, nếu không có ích vì anh ta đã bỏ qua việc đưa ra một ví dụ làm việc tối thiểu.
Andres Riofrio
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.