2015-09-24 4 views
2

Итак, у меня есть Shape.h, Rectangle.h, Circle.h и main.cpp.Как узнать, принадлежит ли объект классу x?

Shape.h получил:

class Shape{ 
public: 
    Shape() {}; 
    ~Shape() { cout << "Destroy Shape."; }; 

    virtual double getArea() = 0; 
    virtual double getCircumference() = 0; 
}; 

Прямоугольник и круг их соответствующий код.

Сейчас в main.cpp я

Shape* newRectangle= new Rectangle(4, 8); 
Shape* newCircle= new Circle(10); 

Все хорошо и денди до сих пор. Вот где я в тупике. Я знаю, что мне нужно делать, я просто не знаю, КАК это сделать.

Я пытаюсь написать функцию, которая проверяет, принадлежит ли Shape * Object Circle или нет.

Это идет что-то вроде этого

if Shape* object belongs to Object-Type Circle, then 
cout << "It's a Circle, bruh!"; 
else 
cout << "Ain't a circle, yo!"; 

я начал после того, как прибегая к помощи с этим:

void check(Shape & object){ 
    Circle& checkObject = dynamic_cast<Circle&>(object); 

} 

Функция в основном будет вызываться через:

check(*newRectangle); 
check(*newCircle); 

Но я гавань» У меня есть ключ к пониманию того, как продолжать :(Любая помощь и объяснение приветствуются. Спасибо!

+0

попробовать http://stackoverflow.com/questions/500493/c-equivalent-of-instanceof – Gordon

+1

сделать класс 'Shape' полиморфные. Это означает, что у него есть хотя бы одна виртуальная функция. Обычно деструктор становится виртуальным. Затем вы можете использовать функциональность C++ RTTI, 'typeid' и' dynamic_cast'. –

+0

Сделайте '~ Shape()' 'virtual'. Это гарантирует 'delete shp;' удаляет весь класс – mksteve

ответ

4

Вы можете сделать это динамически заливку Shape указателя на указатель нужного типа и проверки nullptr:

if (dynamic_cast<Circle*>(object)) { 
    cout << "It's a Circle, bruh!"; 
} 

Это требует выполнения Тип данные включены, и что ваш объект имеет, по крайней мере, одна виртуальная функция (она).

Примечание 1: Если вам нужно что-то сделать, посмотрите, можете ли вы изменить свой дизайн, чтобы вам не пришлось это делать. Например, можно применить несколько шаблонов доставки, такой как посетителя, чтобы избежать этой проверки:

struct ShapeVisitor { 
    virtual ~ShapeVisitor() {} 
    virtual void visitCircle(const Circle* circle); 
    virtual void visitRectangle(const Rectangle* rectangle); 
}; 

class Shape{ 
public: 
    Shape() {}; 
    virtual ~Shape() { cout << "Destroy Shape."; }; 

    virtual double getArea() = 0; 
    virtual double getCircumference() = 0; 
    virtual void Accept(const ShapeVisitor& visitor) = 0; 
}; 

struct Circle : public Shape { 
    virtual void Accept(const ShapeVisitor& visitor) { 
     visitor.visitCircle(this); 
    } 
}; 

struct Rectangle : public Shape { 
    virtual void Accept(const ShapeVisitor& visitor) { 
     visitor.visitRectangle(this); 
    } 
}; 

Теперь вы можете печатать вид формы, которую вы видите, как это:

struct PrintTypeVisitor : public ShapeVisitor { 
    virtual void visitCircle(const Circle* circle) { 
     cout << "It's a Circle, bruh!"; 
    } 
    virtual void visitRectangle(const Rectangle* rectangle) { 
     cout << "It's a Rectangle, bruh!"; 
    } 
} 
... 
PrintTypeVisitor v; 
Shape* object = ... 
object.Accept(v); // This prints dynamic type of the object 

Примечание 2: Вы должны сделать виртуальный виртуальный дескриптор Shape.

+0

Да, я думал о чем-то ссылке. Нулевой или нулевой указатель. Хмм ... попробуй. Благодаря! –

+0

Разве деструктор в базовом классе не должен быть виртуальным для удаления с помощью указателя базового класса для правильной работы? –

+0

@JamesAdkison Да, спасибо за комментарий! Я скопировал код OP, но пропустил не-виртуальный деструктор. – dasblinkenlight

6
  1. Старайтесь избегать логики на основе производных типов. Используйте функции virtual, когда можете.

    class Shape { 
        public: 
         virtual void print(std::ostream& out) const = 0; 
        ... 
    }; 
    

    и реализовать функцию в производных кладах.

    class Circle : public Shape { 
        public: 
         virtual void print(std::ostream& out) const 
         { 
         out << "Got a Circle.\n"; 
         } 
    
        .... 
    }; 
    
  2. Если вы не можете решить проблему с помощью функции с virtual члена, вам нужно обратиться к dynamic_cast.

    Shape* shapePtr = <some pointer>; 
    Circle* circlePtr = dynamic_cast<Circle*>(shapePtr); 
    if (circlePtr) { 
        // Access Circle functionality. 
    } 
    
+0

Сейчас я нахожусь в решении 2. Нельзя поступать иначе. Мне очень трудно понять указатели. BLEH. Что я даю в <некоторый указатель>? Взято из моего примера, что я создал 2 указателя формы? объекты?? как Shape * newRectangle = новый прямоугольник (4, 8); и Shape * newCircle = новый круг (10); –

+0

Я пробовал http://hastebin.com/dalanasudu.xml или я что-то не понял. Но он говорит мне: «Не могу использовать« dynamic_cast »для преобразования из« Shape & »в« Circle * »« –

+0

@NoCanDo. Вы должны написать «Circle * circlePtr = dynamic_cast (& object);' в вашем примере hastebin для преобразования ссылки на указатель. – dasblinkenlight

Смежные вопросы