Incorrect object oriented programming

Динамический тип this указатель является неправильным

Описание

Это начинает работу, вызов функции члена класса определяет, допустим ли вызов.

Вызов функции членства может быть недопустимым по следующим причинам:

  • Вы вызываете функцию членства через указатель функции, который указывает на функцию. Однако типы данных аргументов или возвращаемые значения функции и указателя функции не соответствуют.

  • Вы вызываете чистый virtual функция членства из конструктора класса или деструктора.

  • Вы вызываете virtual функция членства через неправильный this указатель. this указатель хранит адрес объекта, используемого, чтобы вызвать функцию. this указатель может быть неправильным потому что:

    • Вы получаете объект через бросок от другого объекта. Объекты являются экземплярами двух несвязанных классов.

    • Вы выполняете адресную арифметику с указателями на указателе, указывающем на массив объектов. Однако адресная арифметика с указателями заставляет указатель выходить за пределы границ массивов. Когда вы разыменовываете указатель, он не указывает на доступный объект.

Примеры

развернуть все

#include <iostream>
class myClass {
public: 
  void method() {}
};

void main() {
  myClass Obj;
  int (myClass::*methodPtr) (void) = (int (myClass::*) (void)) &myClass::method;
  int res = (Obj.*methodPtr)();
  std::cout << "Result = " << res;
}

В этом примере, указатель methodPtr имеет возвращаются, вводят int но точки к myClass:method это имеет, возвращаются, вводят void. Поэтому, когда methodPtr разыменовывается, проверка Incorrect object oriented programming производит красную ошибку.

#include <iostream>
class myClass {
public:
  void method() {}
};

void main() {
  myClass Obj;
  void (myClass::*methodPtr) (void) =  &myClass::method;
  methodPtr = 0;
  (Obj.*methodPtr)();
}

В этом примере, methodPtr имеет значение NULL когда это разыменовывается.

class Shape {
public:
  Shape(Shape *myShape) {
    myShape->setShapeDimensions(0.0);
  }
  virtual void setShapeDimensions(double) = 0;
};

class Square: public Shape {
  double side;
public:
  Square():Shape(this) {
  }
  void setShapeDimensions(double);
};

void Square::setShapeDimensions(double val) {
  side=val;
}

void main() {
  Square sq;
  sq.setShapeDimensions(1.0);
}

В этом примере, конструктор производного класса Square::Square вызывает конструктора базового класса Shape::Shape() с его this указатель. Конструктор базового класса затем вызывает чистую виртуальную функцию Shape::setShapeDimensions через this указатель. Поскольку вызов чистой виртуальной функции от конструктора не определен, проверка Incorrect object oriented programming производит красную ошибку.

#include <new>

class Foo {
public:
  void funcFoo() {}
};


class Bar {
public:
  virtual void funcBar() {}
};

void main() {
  Foo *FooPtr = new Foo;
  Bar *BarPtr = (Bar*)(void*)FooPtr;
  BarPtr->funcBar();
}

В этом примере, классы Foo и Bar не связаны. Когда Foo* указатель брошен к Bar* указатель и Bar* указатель используется, чтобы вызвать virtual функция членства класса Bar, проверка Incorrect object oriented programming производит красную ошибку.

#include <new>
class Foo {
public:
    virtual void func() {}
};

void main() {
    Foo *FooPtr = new Foo[4];
    for(int i=0; i<=4; i++)
        FooPtr++;
    FooPtr->func();
    delete [] FooPtr;
}

В этом примере, указатель FooPtr точки вне выделенных границ, когда это используется, чтобы вызвать virtual функция членства func(). Это не указывает на доступный объект. Поэтому проверка Incorrect object oriented programming производит красную ошибку.

class Foo {
public:
  virtual int func() {
    return 1;
  }
};

class Ref {
public:
  Ref(Foo* foo) {
    foo->func();
  }
};

class Bar {
private:
  Ref m_ref;
  Foo m_Foo;
public:
  Bar() : m_ref(&m_Foo) {}
};

В этом примере, конструктор Bar::Bar() вызывает конструктора Ref::Ref() с адресом m_Foo перед m_Foo инициализируется. Когда virtual функция членства func называется через указатель, указывающий на &m_Foo, проверка Incorrect object oriented programming производит красную ошибку.

Чтобы воспроизвести результаты, анализируйте только класс Bar использование опции Class (-class-analyzer).

#include <new>

class Foo {
public:
  virtual void funcFoo() {}
};


class Bar: public Foo {
public:
  void funcFoo() {}
};

void main() {
  Foo *FooPtr = new Foo;
  Bar *BarPtr = (Bar*)(void*)FooPtr;
  BarPtr->funcFoo();
}

В этом примере вы можете намереваться вызвать версию производного класса funcFoo но в зависимости от вашего компилятора, вы вызываете версию базового класса или сталкиваетесь с отказом сегментации.

Указатель FooPtr точки к Foo объект. Состав исполнителей неправильно пытается преобразовать Foo* указатель FooPtr к Bar* указатель BarPtr. BarPtr неподвижные точки к основному Foo возразите и не может получить доступ к Bar::funcFoo.

Коррекция – заставляет указатель базового класса указать непосредственно на объект производного класса

Полиморфизм C++ позволяет задавать указатель, который может пересечь иерархию классов, чтобы указать на наиболее выведенную функцию членства. Чтобы реализовать полиморфизм правильно, запустите с указателя базового класса и заставьте его указать на объект производного класса.

#include <new>

class Foo {
public:
  virtual void funcFoo() {}
};


class Bar: public Foo {
public:
  void funcFoo() {}
};

void main() {
  Foo *FooPtr = new Bar;
  FooPtr->funcFoo();
}

Проверяйте информацию

Группа: C++
Язык: C++
Акроним: OOP