Меню

Cannot declare variable to be of abstract type ошибка

EDIT: After spending a bit of time understanding the code I wrote I still don’t know what is wrong with it. This is the base class from which I derived my class:

///ContactResultCallback is used to report contact points
struct  ContactResultCallback
{
    short int   m_collisionFilterGroup;
    short int   m_collisionFilterMask;

    ContactResultCallback()
        :m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
        m_collisionFilterMask(btBroadphaseProxy::AllFilter)
    {
    }

    virtual ~ContactResultCallback()
    {
    }

    virtual bool needsCollision(btBroadphaseProxy* proxy0) const
    {
        bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0;
        collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask);
        return collides;
    }

    virtual btScalar    addSingleResult(btManifoldPoint& cp,    const btCollisionObjectWrapper* colObj0Wrap,int partId0,int index0,const btCollisionObjectWrapper* colObj1Wrap,int partId1,int index1) = 0;
};

Now here is my derived class:

class DisablePairCollision : public btCollisionWorld::ContactResultCallback
{
public:
    virtual btScalar addSingleResult(btManifoldPoint& cp, const btCollisionObject* colObj0, int32_t partId0, int32_t index0, const btCollisionObject* colObj1, int32_t partId1, int32_t index1);

    btDiscreteDynamicsWorld* DynamicsWorld;
};

And below is where I implement the main function. Still not sure why I’m getting this error.

I was using the code below on windows with both vc2010 and code blocks without a problem:

btScalar DisablePairCollision::addSingleResult(btManifoldPoint& cp, const btCollisionObject* colObj0, int32_t partId0, int32_t index0, const btCollisionObject* colObj1, int32_t partId1, int32_t index1)
{
    // Create an identity matrix.
    btTransform frame;
    frame.setIdentity();

    // Create a constraint between the two bone shapes which are contacting each other.
    btGeneric6DofConstraint* Constraint;
    Constraint = new btGeneric6DofConstraint( *(btRigidBody*)colObj0, *(btRigidBody*)colObj1, frame, frame, true );

    // Set limits to be limitless.
    Constraint->setLinearLowerLimit( btVector3(1, 1, 1 ) );
    Constraint->setLinearUpperLimit( btVector3(0, 0, 0 ) );
    Constraint->setAngularLowerLimit( btVector3(1, 1, 1 ) );
    Constraint->setAngularUpperLimit( btVector3(0, 0, 0 ) );

    // Add constraint to scene.
    DynamicsWorld->addConstraint(Constraint, true);
    return 0;
}

Now I’m trying to compile my project on Ubuntu but I am getting this error when I try to use that class:

/home/steven/Desktop/ovgl/src/OvglScene.cpp:211: error: cannot declare variable ‘Callback’ to be of abstract type ‘Ovgl::DisablePairCollision’

  • Forum
  • General C++ Programming
  • Cannot Declare Variable To Be of Abstrac

Cannot Declare Variable To Be of Abstract Type

I’m just trying to see if everything that I have written so far is correct for my program. However whenever I try to compile, I receive there error message:
main.cpp:8: error: cannot declare variable ‘oList’ to be of abstract type ‘OListType<int>’

Below is my code. I can provide the derived abstract template class if need be as well.

Main.cpp

1
2
3
4
5
6
7
8
9
10
11
12
#include "OListType.h"
#include "UListType.h"
#include <iostream>

using namespace std;

int main() {
  OListType<int> oList;
  UListType<int> uList;
  
  return 0;
}

OListType.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#ifndef OListType_h
#define OListType_h

#include "ListType.h"

template <class T>
class OListType: public ListType<T> {
public:
  OListType(size_t=10);
  void insert(const T&);
  //void erase(const T&);
  //bool find(const T&) const;
};

template <class T>
OListType<T>::OListType(size_t n):ListType<T>(n){
}

template <class T>
void OListType<T>::insert(const T& item){
  if (this->count == this->capacity){
    this->capacity *= 2;
    T *temp = new T[this->capacity];
    for(int i=0; i<this->count; ++i)
      temp[i] = this->items[i];
    delete [] this->items;
    this->items = temp;
  }
  int i=this->count-1;
  while (i>=0 && item < this->items[i]) {
    this->items[i+1] = this->items[i];
    --i;
  }
  this->items[i+1] = item;
  ++this->count;
}

#endif 

UListType.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#ifndef UListType_h
#define UListType_h

#include "ListType.h"

template <class T>
class UListType: public ListType<T> {
  public:
    UListType(size_t=10);
    //void insert(const T&);
    //void erase(const T&);
    bool find(const T&) const;
};

template <class T>
UListType<T>::UListType(size_t n):ListType<T>(n){
}

template <class T>
void UListType<T>::insert (const T& items) {
  if (this->count == this->capacity){
    this->capacity *= 2;
    T *temp = new T[this->capacity];
    for(int i=0; i<this->count; ++i)
      temp[i] = this->items[i];
    delete [] this->items;
    this->items = temp;
  }
  this->items[this->count] = items;
  ++this->count;
}

template <class T>
bool ListType<T>::find(const T& findItem) const {
  for (int i=0; i<this->count; ++i){
    if(findItem == items[i])
      return true;
  }
}
#endif 

Last edited on

You can’t create an instance of an abstract class. You have to keep a pointer or reference to it instead. What would happen if you called one of the abstract methods?

Alright, so does that require me to change my whole code? I’m not quite sure I understand. I didn’t think that OListType and UListType were abstract classes. I just thought they inherited from an abstract class.

If you inherited from an abstract class, you need to implement all the virtual members in order to be able to define an instance of it. Make sure you have implemented all of the pure virtual methods from the base class in the derived class.

Alright that was the problem. Thanks for your help!

Topic archived. No new replies allowed.

BlackStoneBlack

half-horse half-gateway

112 / 79 / 42

Регистрация: 10.05.2016

Сообщений: 517

1

Невозможно определить переменную абстрактным типом

13.08.2019, 18:16. Показов 1965. Ответов 4

Метки нет (Все метки)


Добрый день!

Имеется следующий код:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <iostream>
#include <vector>
using namespace std;
 
namespace some
{
    class One
    {
        public:
 
            One() {}
 
            virtual void method() = 0;
 
    };
 
    class Two : public One
    {
        public:
 
            Two() : One() {}
 
            virtual void method() override
            {
                cout << "Method!" << endl;
            }
 
            void add(One element)
            {
                this->elements.push_back(element);
            }
 
        private:
 
            vector<One> elements;
    };
}
 
int main()
{
    some::Two *t = new some::Two;
    delete t;
    return 0;
}

При компиляции выводит ошибку:

error: cannot declare parameter ‘element’ to be of abstract type ‘some::One’
note: because the following virtual functions are pure within ‘some::One’:
note: ‘virtual void some::One::method()’|

Я понимаю, что тут написано, но не понимаю. Можно, конечно, заменить

C++
1
virtual void method() = 0;

…на:

C++
1
virtual void method() {}

…но тогда вызывается метод родительского класса.

Прошу помочь с проблемой. Заранее спасибо!



0



Programming

Эксперт

94731 / 64177 / 26122

Регистрация: 12.04.2006

Сообщений: 116,782

13.08.2019, 18:16

4

Mental handicap

1245 / 623 / 171

Регистрация: 24.11.2015

Сообщений: 2,429

13.08.2019, 18:22

2

Цитата
Сообщение от BlackStoneBlack
Посмотреть сообщение

vector<One> elements;

One должен быть One*.
Соответственно void add(One* element)

Цитата
Сообщение от BlackStoneBlack
Посмотреть сообщение

но тогда вызывается метод родительского класса

А вы какой хотели?)

Добавлено через 51 секунду

Цитата
Сообщение от BlackStoneBlack
Посмотреть сообщение

Я понимаю, что тут написано, но не понимаю.

А оно вам надо?



0



jugu

610 / 415 / 151

Регистрация: 11.01.2019

Сообщений: 1,746

13.08.2019, 18:26

3

Первое, что брякнуло в голову…

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <iostream>
#include <vector>
using namespace std;
 
namespace some
{
    class One
    {
    public:
 
        One() {}
 
        virtual void method() = 0;
 
    };
 
    class Two : public One
    {
    public:
 
        Two() : One() {}
 
        virtual void method() override
        {
            cout << "Method!" << endl;
        }
 
        void add(One* element)
        {
            this->elements.push_back(element);
        }
 
    private:
 
        vector<One*> elements;
    };
}
 
int main()
{
    some::Two *t = new some::Two;
    delete t;
    return 0;
}



0



Azazel-San

13.08.2019, 18:36

Не по теме:

Цитата
Сообщение от jugu
Посмотреть сообщение

Первое, что брякнуло в голову…

И не лень было..



0



95 / 81 / 22

Регистрация: 19.10.2013

Сообщений: 485

13.08.2019, 18:42

5

Лучший ответ Сообщение было отмечено BlackStoneBlack как решение

Решение

Когда вы пишете void add(One element), вы пытаетесь передать копию объекта One, а создать объект абстрактного класса не является возможным — отсюда и ошибка.

Вам надо передавать не копию объекта, а указатель на объект (как уже написали выше).

Цитата
Сообщение от BlackStoneBlack
Посмотреть сообщение

…но тогда вызывается метод родительского класса.

А это снова потому что вы не используете указатель.

Когда вы пишете One one = Two(); у вас создаётся объект Two(), затем вызывается неявный конструктор копирования One в One, Two уничтожается и у вас остаётся только One. Никакого Two уже не существует.

Если же Two создать в куче One *one = new Two();, то указатель *one всегда будет указывать на объект Two.



0



Я получил следующую ошибку:

error: cannot declare variable 'b' to be of abstract type 'B'
note: because the following virtual functions are pure within 'B'
note: virtual bool Serializable::eq(const QString&) const
virtual bool eq( const QString & qs) const = 0;
^
note: virtual bool Serializable::eq(const Serializable*) const
virtual bool eq( const Serializable * o) const = 0;
^

по этому коду:

class Serializable {
public:
virtual  bool eq( const QString & qs) const = 0;
virtual  bool eq( const Serializable * o) const = 0;
};

class JSONSerializable : public Serializable {
public:
virtual  QString toJSON( void) const = 0;

virtual  bool eq( const QString & qs) const {
return toJSON() == qs;
}
virtual  bool eq( const Serializable * o) const {
return eq( (( JSONSerializable *) o)->toJSON());
}
};

class A : public Serializable {  };

class B : public A,
public JSONSerializable {
public:
virtual  QString toJSON( void) const {
return QString( "test!");
}
};

…
B b;
qDebug() << b.toJSON();
…

Я понимаю, что это из-за чисто виртуальных методов или множественного наследования. Эта ошибка действительно заставляет меня плакать. Как я могу заставить его исчезнуть? Буду очень признателен за помощь!

3

Решение

Проблема в том, что B наследует абстрактный класс Serializable дважды:

  • Однажды через свой базовый класс A, а также
  • Еще раз через его другой базовый класс JSONSerializable

В результате вы должны переопределить два чистых виртуальных Serializable дважды.

Поскольку вы задаете вопрос о Bоставаясь абстрактным, я понимаю, что вы не хотели, чтобы все было так: вы хотели B наследовать Serializable только один раз, как если бы это был интерфейс, и использовать JSONSerializableРеализация для «добавления» дополнительного функционала. Если это так, вам нужно унаследовать Serializable фактически, как это:

class Serializable {
public:
virtual  bool eq( const QString & qs) const = 0;
virtual  bool eq( const Serializable * o) const = 0;
};

class JSONSerializable : virtual public Serializable {
public:
virtual  QString toJSON( void) const = 0;

virtual  bool eq( const string & qs) const {
return toJSON() == qs;
}
virtual  bool eq( const Serializable * o) const {
return eq(dynamic_cast<const JSONSerializable*>(o)->toJSON());
}
};

class A : virtual public Serializable {  };

class B : virtual public A,
public JSONSerializable {
public:
virtual  QString toJSON( void) const {
return QString( "test!");
}
};

Добавленный virtual Ключевое слово указывает компилятору, что вам нужна только одна «копия» Serializable база для включения в ваш класс B,

Это изменение устраняет проблему (демонстрация).

2

Другие решения

РЕДАКТИРОВАТЬ: Потратив немного времени на понимание кода, который я написал, я до сих пор не знаю, что с ним не так. Это базовый класс, из которого я получил свой класс:

///ContactResultCallback is used to report contact points
struct  ContactResultCallback
{
    short int   m_collisionFilterGroup;
    short int   m_collisionFilterMask;

    ContactResultCallback()
        :m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
        m_collisionFilterMask(btBroadphaseProxy::AllFilter)
    {
    }

    virtual ~ContactResultCallback()
    {
    }

    virtual bool needsCollision(btBroadphaseProxy* proxy0) const
    {
        bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0;
        collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask);
        return collides;
    }

    virtual btScalar    addSingleResult(btManifoldPoint& cp,    const btCollisionObjectWrapper* colObj0Wrap,int partId0,int index0,const btCollisionObjectWrapper* colObj1Wrap,int partId1,int index1) = 0;
};

Теперь вот мой производный класс:

class DisablePairCollision : public btCollisionWorld::ContactResultCallback
{
public:
    virtual btScalar addSingleResult(btManifoldPoint& cp, const btCollisionObject* colObj0, int32_t partId0, int32_t index0, const btCollisionObject* colObj1, int32_t partId1, int32_t index1);

    btDiscreteDynamicsWorld* DynamicsWorld;
};

А ниже я реализую основную функцию. Все еще не уверен, почему я получаю эту ошибку.

Я без проблем использовал приведенный ниже код в окнах как с vc2010, так и с кодовыми блоками:

btScalar DisablePairCollision::addSingleResult(btManifoldPoint& cp, const btCollisionObject* colObj0, int32_t partId0, int32_t index0, const btCollisionObject* colObj1, int32_t partId1, int32_t index1)
{
    // Create an identity matrix.
    btTransform frame;
    frame.setIdentity();

    // Create a constraint between the two bone shapes which are contacting each other.
    btGeneric6DofConstraint* Constraint;
    Constraint = new btGeneric6DofConstraint( *(btRigidBody*)colObj0, *(btRigidBody*)colObj1, frame, frame, true );

    // Set limits to be limitless.
    Constraint->setLinearLowerLimit( btVector3(1, 1, 1 ) );
    Constraint->setLinearUpperLimit( btVector3(0, 0, 0 ) );
    Constraint->setAngularLowerLimit( btVector3(1, 1, 1 ) );
    Constraint->setAngularUpperLimit( btVector3(0, 0, 0 ) );

    // Add constraint to scene.
    DynamicsWorld->addConstraint(Constraint, true);
    return 0;
}

Теперь я пытаюсь скомпилировать свой проект в Ubuntu, но получаю эту ошибку, когда пытаюсь использовать этот класс:

/home/steven/Desktop/ovgl/src/OvglScene.cpp:211: error: cannot declare variable ‘Callback’ to be of abstract type ‘Ovgl::DisablePairCollision’

Hi Rui,
Yes the WiFi scan example compiles fine (in fact the ESP32 is more sensitive than the WiFi on my phone!)
Indeed everything in the corse so far has been fine until the web server display sensor readings sketch, and I actually have a real world use for this to monitor the temp and humidity in our greenhouse..
I have pasted the code below directly from the Arduino IDE:
/*********
Rui Santos
Complete project details at http://randomnerdtutorials.com
*********/
// Load Wi-Fi library
#include <WiFi.h>
#include <Wire.h>
#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.h>
//uncomment the following lines if you’re using SPI
/*#include <SPI.h>
#define BME_SCK 18
#define BME_MISO 19
#define BME_MOSI 23
#define BME_CS 5*/
#define SEALEVELPRESSURE_HPA (1013.25)
Adafruit_BME280 bme; // I2C
//Adafruit_BME280 bme(BME_CS); // hardware SPI
//Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI
// Replace with your network credentials
const char* ssid = “SSID”;
const char* password = “password”;
// Set web server port number to 80
WiFiServer server(80);
// Variable to store the HTTP request
String header;
void setup() {
Serial.begin(115200);
bool status;
// default settings
// (you can also pass in a Wire library object like &Wire2)
//status = bme.begin();
if (!bme.begin(0x76)) {
Serial.println(“Could not find a valid BME280 sensor, check wiring!”);
while (1);
}
// Connect to Wi-Fi network with SSID and password
Serial.print(“Connecting to “);
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(“.”);
}
// Print local IP address and start web server
Serial.println(“”);
Serial.println(“WiFi connected.”);
Serial.println(“IP address: “);
Serial.println(WiFi.localIP());
server.begin();
}
void loop(){
WiFiClient client = server.available(); // Listen for incoming clients
if (client) { // If a new client connects,
Serial.println(“New Client.”); // print a message out in the serial port
String currentLine = “”; // make a String to hold incoming data from the client
while (client.connected()) { // loop while the client’s connected
if (client.available()) { // if there’s bytes to read from the client,
char c = client.read(); // read a byte, then
Serial.write(c); // print it out the serial monitor
header += c;
if (c == ‘n’) { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that’s the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what’s coming, then a blank line:
client.println(“HTTP/1.1 200 OK”);
client.println(“Content-type:text/html”);
client.println(“Connection: close”);
client.println();

// Display the HTML web page
client.println(“<!DOCTYPE html><html>”);
client.println(“<head><meta name=”viewport” content=”width=device-width, initial-scale=1”>”);
client.println(“<link rel=”icon” href=”data:,”>”);
// CSS to style the table
client.println(“<style>body { text-align: center; font-family: ”Trebuchet MS”, Arial;}”);
client.println(“table { border-collapse: collapse; width:35%; margin-left:auto; margin-right:auto; }”);
client.println(“th { padding: 12px; background-color: #0043af; color: white; }”);
client.println(“tr { border: 1px solid #ddd; padding: 12px; }”);
client.println(“tr:hover { background-color: #bcbcbc; }”);
client.println(“td { border: none; padding: 12px; }”);
client.println(“.sensor { color:white; font-weight: bold; background-color: #bcbcbc; padding: 1px; }”);

// Web Page Heading
client.println(“</style></head><body><h1>ESP32 with BME280</h1>”);
client.println(“<table><tr><th>MEASUREMENT</th><th>VALUE</th></tr>”);
client.println(“<tr><td>Temp. Celsius</td><td><span class=”sensor”>”);
client.println(bme.readTemperature());
client.println(” *C</span></td></tr>”);
client.println(“<tr><td>Temp. Fahrenheit</td><td><span class=”sensor”>”);
client.println(1.8 * bme.readTemperature() + 32);
client.println(” *F</span></td></tr>”);
client.println(“<tr><td>Pressure</td><td><span class=”sensor”>”);
client.println(bme.readPressure() / 100.0F);
client.println(” hPa</span></td></tr>”);
client.println(“<tr><td>Approx. Altitude</td><td><span class=”sensor”>”);
client.println(bme.readAltitude(SEALEVELPRESSURE_HPA));
client.println(” m</span></td></tr>”);
client.println(“<tr><td>Humidity</td><td><span class=”sensor”>”);
client.println(bme.readHumidity());
client.println(” %</span></td></tr>”);
client.println(“</body></html>”);

// The HTTP response ends with another blank line
client.println();
// Break out of the while loop
break;
} else { // if you got a newline, then clear currentLine
currentLine = “”;
}
} else if (c != ‘r’) { // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
}
}
// Clear the header variable
header = “”;
// Close the connection
client.stop();
Serial.println(“Client disconnected.”);
Serial.println(“”);
}
}

0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии

А вот еще интересные материалы:

  • Яшка сломя голову остановился исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного где ошибка
  • Cannot be resolved to a type ошибка java
  • Cannot add or update a child row a foreign key constraint fails ошибка