When you declare a summary of something before using it, this is called a forward declaration.
When making a forward declaration to a function, the compiler has everything it needs in order to parse code which invokes that function: the name of the function, the type returned, the number of arguments, and the type of each argument.
But when making a forward declaration to a class, the compiler only knows that this particular symbol (generic_iterator
in your case) is a class. Subsequently, the only thing you can do with it before it has been fully defined is to declare a pointer to it. (And people with more knowledge of C++ than me might know one or two additional arcane uses.) You cannot invoke any of its members, because the compiler does not yet know its structure. Your code is trying to invoke the constructor of your forward-referenced class, but the compiler does not know of any such constructor yet.
I do not know of any easy way to resolve this problem. Others might have some better solutions, but the way I tend to resolve this problem is by moving all of the code that needs to access members of a forwardly declared class from the .h
file to the .cpp
file. So, in your case, in the .h
file I would simply write iterator begin();
and then in the .cpp
file I would write generic_iterator darray::begin() {return iterator(ptrarray); }
.
This would compile, because at that moment the complete class definition of generic_iterator
is known.
Я сталкиваюсь с ошибкой ниже — когда я просто предоставляю определение класса, а затем объявляю его позже. Мое понимание было до тех пор, пока мы делаем это, поскольку я много раз делал для определения функции, компилятор понимает это, но, похоже, мое понимание ошибочно, если кто-то поможет мне понять, что недостает в понимании того, как объявлять класс.
error C2027: use of undefined type 'generic_iterator'
note: see declaration of 'generic_iterator
Не работает — ошибка показанная выше
#include <iostream>
class generic_iterator;
class darray
{
public:
typedef generic_iterator iterator;
darray();
darray(int size);
~darray();
int& at(int index);
int& operator [](int i);
int* data(void);
bool empty();
void fill(int val);
void print();
size_t max_size();
iterator begin() {return iterator(ptrarray); }
iterator end() { return iterator(ptrarray + size); }
private:
int *ptrarray;
int num_elements;
int size;
};
class generic_iterator
{
public:
generic_iterator(int *ptr);
~generic_iterator();
generic_iterator& operator++(); // pre-increment
generic_iterator operator++(int); // post-increment
private:
int *iptr;
};
Работает : Когда весь класс объявлен первым
class generic_iterator
{
public:
generic_iterator(int *ptr);
~generic_iterator();
generic_iterator& operator++(); // pre-increment
generic_iterator operator++(int); // post-increment
private:
int *iptr;
};
class darray
{
public:
typedef generic_iterator iterator;
darray();
darray(int size);
~darray();
int& at(int index);
int& operator [](int i);
int* data(void);
bool empty();
void fill(int val);
void print();
size_t max_size();
iterator begin() {return iterator(ptrarray); }
iterator end() { return iterator(ptrarray + size); }
private:
int *ptrarray;
int num_elements;
int size;
};
3
Решение
Когда вы объявляете резюме чего-либо перед его использованием, это называется предварительная декларация.
Делая прямое объявление функции, у компилятора есть все, что ему нужно для анализа кода, который вызывает эту функцию: имя функции, возвращаемый тип, количество аргументов и тип каждого аргумента.
Но, делая прямое объявление классу, компилятор знает только, что этот конкретный символ (generic_iterator
в вашем случае) это класс. Впоследствии, единственное, что вы можете сделать с ним до того, как оно будет полностью определено, это объявить указатель на него. (И люди с большим знанием C ++, чем я, могут знать одно или два дополнительных тайных использования.) Вы не можете вызывать ни одного из его членов, потому что компилятор еще не знает его структуру. Ваш код пытается вызвать конструктор вашего класса с прямой ссылкой, но компилятор пока не знает ни одного такого конструктора.
Я не знаю ни одного простого способа решить эту проблему. У других могут быть более удачные решения, но я стараюсь решить эту проблему путем перемещения всего кода, который необходим для доступа к членам заранее объявленного класса, из .h
подать в .cpp
файл. Итак, в вашем случае, в .h
файл я бы просто написал iterator begin();
а затем в .cpp
файл я бы написал generic_iterator darray::begin() {return iterator(ptrarray); }
,
Это скомпилируется, потому что на тот момент полное определение класса generic_iterator
известен.
2
Другие решения
Компилятор должен знать определение класса generic_iterator
чем занимается анализ этих определений функций
iterator begin() {return iterator(ptrarray); }
iterator end() { return iterator(ptrarray + size); }
В противном случае невозможно сказать, является ли этот код правильным, является ли класс generic_iterator
имеет конструктор, который может быть вызван с одним аргументом.
Примите во внимание, что было бы правильно объявить оператор постоянного индекса вместе с оператором непостоянного значения. Например
int& operator [](int i);
const int& operator [](int i) const;
или же
int& operator [](int i);
int operator [](int i) const;
Также попробуйте использовать классификатор const
с функциями-членами, которые не изменяют сам объект, как, например, empty
или же max_size
или, может быть print
bool empty() const;
void print() const;
size_t max_size()const;
3
- Remove From My Forums
-
Question
-
I’m passing a handle to form to a ref class. However, I can’t use the handle in the ref class due to the form being an undefined type. I’m not sure how to resolve this since a forward declaration is insufficent. There has to be a fairly simple way to cope
with something like this. I have a couple of reference books but none seem deal with this sort of problem.error message:
testClass.h(22) : error C2027: use of undefined type ‘formPointer2::Form1’
testClass.h(6) : see declaration of ‘formPointer2::Form1’Class with error in it:
#pragma once;
#include «Form1.h»
//forward declaration for namespace
namespace formPointer2 {ref class Form1;}using namespace formPointer2;
namespace formPointer2
{public ref class testClass
{public:
testClass(){}testClass(Form1^ z)
{
x=z;
x->button1->Text = «bye»; //line that is causing c2027 undefined type ‘formPointer2::Form1’ error
}
private:
Form1^ x;};
}
Form class that is referenced:
#pragma once
#include «testClass.h»
namespace formPointer2 {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;public ref class Form1 : public System::Windows::Forms::Form
{
public:
Form1(void)
{
InitializeComponent();testClass^ tc = gcnew testClass(this);
}protected:
~Form1()
{
if (components)
{
delete components;
}
}
private: System::Windows::Forms::Button^ button1;
private: System::Windows::Forms::TextBox^ textBox1;
protected:private:
System::ComponentModel::Container ^components;#pragma region Windows Form Designer generated code
void InitializeComponent(void)
{
this->button1 = (gcnew System::Windows::Forms::Button());
this->textBox1 = (gcnew System::Windows::Forms::TextBox());
this->SuspendLayout();
//
// button1
//
this->button1->Location = System::Drawing::Point(92, 188);
this->button1->Name = L»button1″;
this->button1->Size = System::Drawing::Size(96, 24);
this->button1->TabIndex = 0;
this->button1->Text = L»button1″;
this->button1->UseVisualStyleBackColor = true;
//
// textBox1
//
this->textBox1->Location = System::Drawing::Point(54, 96);
this->textBox1->Name = L»textBox1″;
this->textBox1->Size = System::Drawing::Size(165, 20);
this->textBox1->TabIndex = 1;
//
// Form1
//
this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(284, 262);
this->Controls->Add(this->textBox1);
this->Controls->Add(this->button1);
this->Name = L»Form1″;
this->Text = L»Form1″;
this->ResumeLayout(false);
this->PerformLayout();}
#pragma endregion
};Thanks
Dave
David Pantaleoni
Answers
-
I’m passing a handle to form to a ref class. However, I can’t use the handle in the ref class due to the form being an undefined type. I’m not sure how to resolve this since a forward declaration is insufficent.
Maybe try like this
// testClass.h
#pragma once // no semi-colon
// #include «Form1.h» (remove this line — circular dependency)
namespace formPointer2 {
// forward declare Form1
public ref class Form1; // note public
// define testClass
public ref class testClass
{
public:
testClass();
testClass(Form1^ z);
};
} //namespace FormPointer2
You also need to move the parts of the implementation of testClass that use Form1 into a separate file testClass.cpp.
// testClass.cpp
#include «testClass.h»
#include «Form1.h»
using namespace formPointer2;
testClass::testClass()
{
}
testClass::testClass(Form1^ z)
{
// you can use Form1 here
}
If you are not familiar with circular dependency in C++ you can read about it here:
http://en.wikipedia.org/wiki/Circular_dependency
David Wilkinson | Visual C++ MVP
-
Marked as answer by
Monday, July 4, 2011 2:24 AM
-
Marked as answer by
This topic has been deleted. Only users with topic management privileges can see it.
I’ve created a Qt widget application project, the mainwindow just being the default generated mainwindow and after a while the mainwindow.cpp wouldn’t compile, even after commenting out everything that I had added to the .h or .cpp, giving the following errors on the initializer and destuctor :
mainwindow.cpp:7: error: allocation of incomplete type ‘Ui::MainWindow’
mainwindow.cpp:15: warning: deleting pointer to incomplete type ‘Ui::MainWindow’ may cause undefined behavior
mainwindow.cpp:7: error: C2027: use of undefined type ‘Ui::MainWindow’
mainwindow.cpp:9: error: C2027: use of undefined type ‘Ui::MainWindow’
mainwindow.cpp:9: error: C2227: left of ‘->setupUi’ must point to class/struct/union/generic type
mainwindow.cpp:15: warning: C4150: deletion of pointer to incomplete type ‘Ui::MainWindow’; no destructor called
Code (Minus previously mentioned commented out bits):
mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp:
#include «mainwindow.h»
#include «ui_mainwindow.h»
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
This is the same as the default generated class, and another project which complies perfectly and doesn’t give any errors, so I’m really confused as to what is happening, any help would be appreciated.
Hi and welcome to the forums.
Try to delete the build folder and then Rebuild all.
There can be left overs from other compiles.
@mrjj The error still persists after doing that
Hi,
Can you show your .pro file ?
@RanDev123 said in error: C2027: use of undefined type ‘Ui::MainWindow’:
mainwindow
Looks like you have deleted mainwindow.ui file from the project. Is the file called mainwindow.ui listed under Forms ? Just check you have commented this line in your pro file under FORMS.
@SGaist
#————————————————-
Project created by QtCreator 2018-12-09T17:41:52
#————————————————-
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = CPU_Simulation
TEMPLATE = app
The following define makes your compiler emit warnings if you use
any feature of Qt which has been marked as deprecated (the exact warnings
depend on your compiler). Please consult the documentation of the
deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
You can also make your code fail to compile if you use deprecated APIs.
In order to do so, uncomment the following line.
You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
CONFIG += c++11
SOURCES +=
main.cpp
controlunit.cpp
register.cpp
memorybus.cpp
databus.cpp
addressbus.cpp
controlbus.cpp
arithlogunit.cpp
indatabus.cpp
mainwindow.cpp
alucontrolbus.cpp
memory.cpp
binaryutilities.cpp
HEADERS +=
controlunit.h
register.h
memorybus.h
databus.h
addressbus.h
controlbus.h
arithlogunit.h
indatabus.h
mainwindow.h
alucontrolbus.h
memory.h
binaryutilities.h
FORMS +=
mainwindow.ui
Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
@dheerendra
Its still there under forms
I can edit its design and stuff, its also still in the project folder and in the .pro file
Do you see following header files under build directory ? > #include «ui_mainwindow.h»
Can you paste the content of the above file ? It is possible that you have changed the object name of MainWindow object in designer.
@dheerendra The class in the ui_mainwindow.h file was called MainWindoe instead of MainWindow, I think I made a spelling mistake when creating the project, but I thought I corrected it in all relevant files, I don’t know why this persisted, even after deleting the build folder, I changed the name and it complies now, thank you
Looks like you changed in the names files. Actually you should change the object name in the designer. Look at the property window in Designer. It has property called objectName. Looks like you have changed this also.
In some cases, your system may generate an error indicating error c2027 Use of undefined type. There can be many reasons for this error.
PC running slow?
Improve the speed of your computer today by downloading this software — it will fix your PC problems.
Isn’t That The Reason You Are Looking For? Explore Other Questions Called Direct Declaration Of C ++ Class Syntax, Or Clear Up Your Own Question.
If you declare a summary of only one thing before using it, this is called a new provisional declaration.
When you pre-declare a function, the compiler has all the ideas it needs to parse the code that calls that function: the exact name of the function, the type of the return name, the number to be specified in the arguments is displayed. , and type de for each argument.
But when you explicitly declare each class, the compiler only knows that that particular symbol (in your case generic_iterator
) is definitely a class. Then the only topic you can do with it before it is fully defined is to successfully declare a pointer to it. (And people with more C ++ knowledge than I might know about one or two different secret applications.) You cannot call all members, becausethe compiler does not yet know their structure. Your scope code is trying to call a constructor with the previously specified class, but the compiler does not yet know about such a constructor.
I don’t know of an easy way to solve this problem. Others will probably have better solutions, but I want to fix this by moving all the code that is required to access the members of the declared class to the beginning of .h
> directly in .cpp
file. In this particular case, I would just write iterator begin ();
in .h
file then I would just write in .cpp
file which I would probably write generic_iterator darray :: begin () return iterator (ptrarray);
.
This will help because at this point the full definition of the generic_iterator
program is known.
answered Nov 15 15 at 21:36.
47.8k
KThe compiler wants to know the definition of the grouping generic_iterator
when parsing these operation definitions
PC running slow?
ASR Pro is the ultimate solution for your PC repair needs! Not only does it swiftly and safely diagnose and repair various Windows issues, but it also increases system performance, optimizes memory, improves security and fine tunes your PC for maximum reliability. So why wait? Get started today!
begin () iterator return iterator (ptrarray);iterator end () repetition + iterator (ptraarray size);
Otherwise, we will not be able to determine if this code is correct, i.e. does the class generic_iterator
already have a constructor that can be called with an argument.
Note that it would be correct to declare the index ruthless using a non-constant operator. For example
int & operator [] (int i);const int & master [] (int i) const;
int & operator [] (int i);int network [] (int i) const;
Also try using the const
qualifier with member functions that never modify the object itself, like for perfect empty
or max_size
or, maybe print
empty bool () const;void print () const;size_t max_size () const;
answered Nov 15 at 21:34
232k
Improve the speed of your computer today by downloading this software — it will fix your PC problems.
Hier Können Sie Den Fehler C2027 Mit Einfacher Verwendung In Bezug Auf Einen Undefinierten Typ Beheben
Ecco Come Risolvere I Problemi C2027 Con Il Semplice Utilizzo Di Un Tipo Non Definito
Dit Is De Eenvoudigste Manier Om Fout C2027 Op Te Lossen Met Eenvoudig Verbruik Van Een Niet-gedefinieerd Type
Voici Comment Corriger L’erreur C2027 Avec Une Utilisation Simple Dans Un Type Non Défini
Aqui Está O Que Corrigir O Erro C2027 Com O Simples Uso De Tipo Indefinido
정의되지 않은 유형을 사용하여 실수 C2027을 수정하는 방법은 다음과 같습니다.
Så Här Blir Du Av Med Fel C2027 Med Enkel Användning Av Odefinierad Typ
Вот способы исправить ошибку C2027 с помощью простого использования неопределенного типа
Oto Jak Naprawić Błąd C2027 Za Pomocą Prostego Użycia Niezdefiniowanego Typu
Aquí Se Explica Cómo Corregir El Error C2027 Con El Uso Simple De Tipo Indefinido
Здравствуйте. Я новичок в C++. Программирую в VisualStudio2008 Возникла проблема при подключении заголовочных файлов. У меня есть файл MyClasses.h:
#ifndef MYCLASSES_H
#define MYCLASSES_H
namespace my {
// Some template classes
...
MyClass {declaration} // My class (not template) contains static methods only
// Other classes declaration
};
#endif
Соответственно есть файл MyClasses.cpp:
namespace my {
// implementation of MyClass and other classes
}
MyClass состоит из нескольких статических методов и всё (без переменных). Заголовочный файл уже используется как минимум один раз в другом проекте (но в том же решении). Теперь возникла необходимость подключить его в тот же проект, в котором он (MyClasses.h) определён. Но при подключении я не могу использовать ни MyClass::method() ни my::MyClass::method() (error C2653: ‘MyClass’ : is not a class or namespace name + error C3861: ‘method’: identifier not found). Пробовал объявлять (просто объявлять) MyClass в том файле, куда хочу его подключить:
#include "MyClasses.h"
class MyClass;
но компилятор не видит реализацию класса (error C2027: use of undefined type ‘MyClass’).
Подскажите пожалуйста мне непутёвому, как правильно подключить MyClasses.h? Заранее спасибо
UPD: Если я просто делаю #include "MyClasses.h"
, то получаю
error C2653: 'MyClass' : is not a class or namespace name
на строчке
MyClass::StaticMethod(); // или так my::MyClass::StaticMethod();
Если я использую предварительное объявление класса так
#include "MyClasses.h";
class MyClass;
или так
#include "MyClasses.h";
namespace my { class MyClass; }
то получаю ошибку error C2027: use of undefined type 'my::MyClass'
на строчке my::MyClass::StaticMethod();