Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
I am trying to iterate through an array to objects to set different attributes of those objects. The attributes of my objects may change over time.
My code as a simplified example:
// MyClass.h
class MyClass
{
/* class definitions */
};
extern MyClass object;
// MyClass.cpp
#include MyClass.h
/* Constructors, Destructors, Functions */
// main.cpp
void reload_objects();
int main()
{
MyClass object[20];
reload_objects();
{
void reload_objects();
{
for (int i = 0; i < 20; i++){
object[i].setProperties(/*args*/);
}
}
I am getting an error error: No match for 'operator[]' (operand types are ‘MyClass’ and ‘int’). If I move the for loop into main it compiles and runs fine.
What is causing this error?
Would it be easier or in some way better to use std::vector<MyClass> object(20) in some way?
There are several mistakes in your given code snippet. You can correct them as i have shown below. I have added comments wherever i have made changes.
MyClass.h
#ifndef MYCLASS_H
#define MYCLASS_H
// MyClass.h
class MyClass
{
/* class definitions */
public:
MyClass() = default;
};
extern MyClass object[20]; //declare object as an array
#endif
MyClass.cpp
// MyClass.cpp
#include "MyClass.h"
/* Constructors, Destructors, Functions */
main.cpp
#include <iostream>
#include "MyClass.h"
MyClass object[20]; // define object here instead of inside main()
void reload_objects(); // reload_objects() doesnt take any argument by looking at its call and definiton
int main()
{
// MyClass object[20]; //don't define object here
reload_objects();
}
void reload_objects() //you had a semicolon here so i removed it
{
for (int i = 0; i < 20; i++){
object[i].setProperties(/*args*/);
;
}
}
Also don't forget to add the definition and declaration of your other member functions like setProperties in the above example for it to work. These are some of the changes that i made:
You should declare object as an array of size 20 inside MyClass.h.
Define object outside of main() inside main.cpp as i did in my example.
Declare the function reload_objects() with no arguments in main.cpp.
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
//TreeBox.h
#pragma once
#include "ListBox.h"
struct ItemInfo
{
std::string _fileName;
std::string _childName;
std::string _time;
std::string _format;
std::string _size;
std::string _nodeKey;
};
class TreeBox
{
...
}
//ListBox.h
class
{
public:
std::vector<ItemInfo> _itemList; //compile error
}
I wanna use std::vector in "ListBox.h" from using struct in "TreeBox.h"
but it was compile error allocator C2903
how do I use that?
You need not to include ListBox.h in TreeBox.h
Always follow practice of including standard libraries first and then the .h files
#pragma once
#include <vector>
#include <string>
class ListBox;
struct ItemInfo
{
std::string _fileName;
std::string _childName;
std::string _time;
std::string _format;
std::string _size;
std::string _nodeKey;
};
class TreeBox
{
};
#pragma once
#include <initializer_list>
#include "TreeBox.h"
class ListBox
{
public:
std::vector <ItemInfo> _itemList;
private:
};
Simply add #include <vector> to the top of your header to include the STL vector. #including a file header at the top of a file allows you to access the objects defined in that header.
You're including ListBox.h at the beginning of TreeBox.h. Specifically, you're including it before the part of TreeBox.h that defines ItemInfo.
So, you're trying to define a vector<ItemInfo> before the compiler knows what an ItemInfo might be, and it doesn't like that.
Rearrange your definitions so by the time the compiler sees the code trying to create a vector<ItemInfo>, it has already seen the definition of ItemInfo (and be sure you've included <vector>, in case you don't have that yet).
So with things in the correct order, you'd have something like this:
#include <vector> // First, tell the compiler about `vector`
class ItemInfo { // ...and `ItemInfo`
// ...
};
class ListBox {
std::vector<ItemInfo> itemList; // *Then* we can use `vector` and `ItemInfo`
// ...
};
If you want some of the pieces of that to be in separate headers that you #include, that's fine--but you still need to get the definitions in the right order.
i have problem with my small project. I have two classes in it.
Problem:
error: 'Display' was not declared in this scope
Display is a class. Here is code:
//main.cpp
#include <iostream>
#include "Display.h"
#include "Polynomial.h"
using namespace std;
int main()
{
Polynomial prr;
prr.show();
cout<<endl;
cout<<"Enter x= ";
int x;
cin>>x;
cout<<endl;
cout<<"value for x="<<x<<endl<<"y="<<prr.value(x);
Display aa; // this doesn't work
//abc.show();
return 0;
}
//Display.h
#ifndef DISPLAY_H
#define DISPLAY_H
class Display
{
std::vector <vector <char> > graph;
public:
Display(int a, int b);
//friend void lay(Polynomial abc,Display cba);
//void show();
};
#endif // DISPLAY_H
I was thinking that maybe vectors are doing problems. I tested it without vectors, but it didn't change anthing.
//Display.cpp
#include "Display.h"
#include <iostream>
using namespace std;
Display::Display(int a, int b)
{
//ctor
if(a%2==0)
a++;
if(b%2==0)
b++;
vector <char> help;
vector <char> mid;
for(int i=0; i<b; i++)
{
mid.push_back('-');
if(i==(b+1)/2)
help.push_back('|');
else
help.push_back(' ');
}
for(int i=0; i<a; i++)
{
if(i==(a+1)/2)
graph.push_back(mid);
else
graph.push_back(help);
}
}
Now it's Polynomial class it's working fine, but Display class no, and i don't know why.
//Polynomial.h
#ifndef POLYNOMIAL_H
#define POLYNOMIAL_H
#include <vector>
//class Display;
class Polynomial
{...}
#endif // POLYNOMIAL_H
//Polynomial.cpp
#include "Polynomial.h"
#include <iostream>
#include <windows.h>
#include <cmath>
using namespace std;
// constructors and methods here
// everything here working fine
Edit:
After few tries i am one step back,
Now in Display.h
i have error :
error: 'vector' does not name a type
So i included vector lib.
But it didn't help.
Error Number 1:
You defined a constructor with 2 parameters
Display(int a, int b);
But when you call
Display aa;
Compiler try to instantiate a Display object with a default constructor, that you disabled defining a custom costructor;
you have 2 possibilities:
Adding a default constructor like
Display() = default;
or
Display() { /* do whatever you want to init with default parameter */}
Instantiate your variable using the constructor you defined
Display aa{0,0};
Error number 2:
std::vector < std::vector <char> > graph;
You declared vector<char> instead of std::vector<char>
See a Live Example
One reason is that your Display class has no default constructor, considering you're creating object like Display aa; . A default constructor is the constructor that has no arguments. Default constructors are provided implicitly by compiler as synthesized default constructor only if you don't provide any constructors to your class. If you provide your own constructors to your class, you must also explicitly provide a default constructor. So in your case, you should actually create Display object like this Display aa(argument, argument); by providing arguments. However, If you want to create object like Display aa; then add either Display () { } or Display() = default; in your Display.h file.
Considering you created object like the way I described but still getting an error, another reason could be that you're not compiling the source file that contains the Display (int,int); constructor definition (not just declaration as you did in your header file) along with the source file that contains the main function. If you did that but still getting an error in compilation, then I would assume it is a compiler issue and try adding a forward declaration class Display; which should compile the code. But the definition of Display has to be within the visible range of main function otherwise a forward declaration would do nothing.
In any case, you have to make sure the definition of your class is within the visible range of the main function that creates the class object. A class type with only declaration without a definition is called incomplete type and you cannot create an object of incomplete type. So the declaration of your Display (int,int); constructor in the Display.h is not enough. You also need a definition of that within the visible range of main function. You can either do that in the same file as main, same file as header, or a separate source file (which is the best practice) that has the complete definition of Display class, its data members, and member functions. However, you must make sure to compile that source file along with the source file containing main.
Is there a way to avoid the Graph:: repetition in the implementation file, yet still split the class into header + implementation? Such as in:
Header File:
#ifndef Graph_H
#define Graph_H
class Graph {
public:
Graph(int n);
void printGraph();
void addEdge();
void removeEdge();
};
#endif
Implementation File:
Graph::Graph(int n){}
void Graph::printGraph(){}
void Graph::addEdge(){}
void Graph::removeEdge(){}
I'm guessing this is to avoid lots of "unnecessary typing". Sadly there's no way to get rid of the scope (as many other answers have told you) however what I do personally is get the class defined with all my function prototypes in nice rows, then copy/paste into the implementation file then ctrl-c your ClassName:: on the clip board and run up the line with ctrl-v.
If you want to avoid typing the "Graph::" in front of the printGraph, addEdge etc., then the answer is "no", unfortunately. The "partial class" feature similar to C# is not accessible in C++ and the name of any class (like "Graph") is not a namespace, it's a scope.
No there's not. Not directly at least. You could go for preprocessor tricks, but don't do it.
#define IMPL Graph::
IMPL Graph(int n){}
void IMPL printGraph(){}
void IMPL addEdge(){}
void IMPL removeEdge(){}
Also, you shouldn't even want to do it. What's the point. Besides it being a C++ rule, it lets you know you're actually implementing a member function.
One option is using. If you have method definitions which are in a cpp file that never gets #included, then using is safe (doesn't affect other files):
foo.h:
class FooLongNameSpecialisationsParamaters
{
int x_;
public:
int Get () const;
void Set (int);
};
foo.cpp:
#include "foo.h"
using Foo = FooLongNameSpecialisationsParamaters;
int Foo::Get () const
{
return x_;
}
void Foo::Set (int x)
{
x_ = x;
}
main.cpp:
#include "foo.h"
int main ()
{
//Foo foo; <-- error
FooLongNameSpecialisationsParamaters foo;
return 0;
}
No, there is no way to avoid it. Otherwise, how would you know if a given function definition is for a class function or for a static function?
If you are asking if you can define a member function such as Graph::printGraph without specifying the class name qualification, then the answer is no, not the way that you want. This is not possible in C++:
implementation file:
void printEdge(){};
The above will compile just fine, but it won't do what you want. It won't define the member function by the same name within the Graph class. Rather, it will declare and define a new free function called printEdge.
This is good and proper, if by your point of view a bit of a pain, because you just might want two functions with the same name but in different scopes. Consider:
// Header File
class A
{
void foo();
};
class B
{
void foo();
};
void foo();
// Implementation File
void foo()
{
}
Which scope should the definition apply to? C++ does not restrict you from having different functions with the same names in different scopes, so you have to tell the compiler what function you're defining.
//yes it is possible using preprocessor like this:
#define $ ClassName //in .cpp
void $::Method1()
{
}
//or like this: in the header .h:
#undef $
#define $ ClassName'
// but you have to include the class header in last #include in your .cpp:
#include "truc.h"
#include "bidule.h" ...
#include "classname.h"
void $::Method() { }
//i was using also
#define $$ BaseClass
//with single inheritance than i can do this:
void $::Method()
{
$$::Method(); //call base class method
}
//but with a typedef defined into class like this it's better to do this:
class Derived : Base
{
typedef Base $$;
}
EDIT: I misread your question. This would be an answer to the question whether you can split header-files. It doesn't help you to avoid using LongClassName::-syntaxes, sorry.
The simple answer: You can split up c++-file, but you can not split up header-files.
The reason is quite simple. Whenever your compiler needs to compile a constructor, it needs to know exactly how many memory it needs to allocate for such an object.
For example:
class Foo {
double bar; //8 bytes
int goo; //4 bytes
}
new Foo() would require the allocation of 12 bytes memory. But if you were allowed to extend your class definitions over multiple files, and hence split header files, you could easily make a mess of this. Your compiler would never know if you already told it everything about the class, or whether you did not. Different places in your code could have different definitions of your class, leading to either segmentation faults or cryptic compiler errors.
For example:
h1.h:
class Foo {
double bar; // 8 bytes
int goo; // 4 bytes
}
h2.h:
#include "h1.h"
class Foo {
double goo; // 8 bytes
} // we extend foo with a double.
foo1.cpp:
#include "foo1.h"
Foo *makeFoo() {
return new Foo();
}
foo2.cpp:
#include "foo2.h"
void cleanupFoo(Foo *foo) {
delete foo;
}
foo1.h:
#include "h1.h"
Foo *makeFoo();
foo2.h:
#include "h1.h"
#include "h2.h"
void cleanupFoo(Foo *foo)
main.cpp:
#include foo1.h
#include foo2.h
void main() {
Foo *foo = makeFoo();
cleanupFoo(foo);
}
Carefully check what happens if you first compile main.cpp to main.o, then foo1.cpp to foo1.o and foo2.cpp to foo2.o, and finally link all of them together. This should compile, but the makeFoo() allocates something else then the cleanupFoo() deallocated.
So there you have it, feel free to split .cpp-files, but don't split up classes over header files.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
Note: I have searched thoroughly on SO and the solutions posted for other's with similar questions are not working for me here.
I am writing my own custom 'string-like' class in C++, and am encoutering the following errors when compiling:
./PyString.h:8:11: error: out-of-line declaration of 'PyString' does
not match any declaration in 'PyString' PyString::PyString (char*);
^
./PyString.h:9:11: error: definition of implicitly declared destructor PyString::~PyString (void);
pystring.cpp:4:7: error: redefinition of 'PyString' class PyString {
As for the first and second errors, moving around the destructor into the class definition itself in the cpp file did not work.
As for the third error, I can't seem to fix it - I'm not redefining the class!
Here is pystring.h:
#ifndef PYSTRING_INCLUDED
#define PYSTRING_INCLUDED
class PyString {
char* string;
};
PyString::PyString (char*);
PyString::~PyString (void);
#endif
Here is pystring.cpp:
#include "PyString.h"
#define NULL 0
class PyString {
char* string = NULL;
public:
PyString(char inString) {
string = new char[inString];
};
~PyString(void) {
delete string;
};
};
For reference, here is the compile output as a screenshot:
Any help is greatly appreciated.
You're defining your class PyString in your header AND in your cpp file, and also, a function definition doesn't need a ; at it's end.
And... your function prototypes needs to be in your class declaration in your header :
pystring.h
class PyString {
public: //ALWAYS indicate what is public/private/protected in your class
PyString (char* inString);
~PyString (); // Don't put void when there's no parameter
private: // All attributes are private
char* string;
};
pystring.cpp
#include "PyString.h"
PyString::PyString(char* inString) {
string = inString; // Avoid using new unless you're forced to
}
PyString::~PyString() {
}
Oh yes you are! pystring.h contains
class PyString {
char* string;
};
which is a class declaration. The declarations PyString::PyString (char*);
and PyString::~PyString (void); need to be inside that declaration.
But you have something similar in pystring.cpp, specifying additional functions, and defining some of them. That's what your compiler is telling you.
Normally, you fully define a class in a header (i.e. all members, and the declaration of the member functions), and implement the member functions of that class in a source file.
The moral of the story here: you can't really learn C++ by trial and error. Get a good book!
Is there a way to avoid the Graph:: repetition in the implementation file, yet still split the class into header + implementation? Such as in:
Header File:
#ifndef Graph_H
#define Graph_H
class Graph {
public:
Graph(int n);
void printGraph();
void addEdge();
void removeEdge();
};
#endif
Implementation File:
Graph::Graph(int n){}
void Graph::printGraph(){}
void Graph::addEdge(){}
void Graph::removeEdge(){}
I'm guessing this is to avoid lots of "unnecessary typing". Sadly there's no way to get rid of the scope (as many other answers have told you) however what I do personally is get the class defined with all my function prototypes in nice rows, then copy/paste into the implementation file then ctrl-c your ClassName:: on the clip board and run up the line with ctrl-v.
If you want to avoid typing the "Graph::" in front of the printGraph, addEdge etc., then the answer is "no", unfortunately. The "partial class" feature similar to C# is not accessible in C++ and the name of any class (like "Graph") is not a namespace, it's a scope.
No there's not. Not directly at least. You could go for preprocessor tricks, but don't do it.
#define IMPL Graph::
IMPL Graph(int n){}
void IMPL printGraph(){}
void IMPL addEdge(){}
void IMPL removeEdge(){}
Also, you shouldn't even want to do it. What's the point. Besides it being a C++ rule, it lets you know you're actually implementing a member function.
One option is using. If you have method definitions which are in a cpp file that never gets #included, then using is safe (doesn't affect other files):
foo.h:
class FooLongNameSpecialisationsParamaters
{
int x_;
public:
int Get () const;
void Set (int);
};
foo.cpp:
#include "foo.h"
using Foo = FooLongNameSpecialisationsParamaters;
int Foo::Get () const
{
return x_;
}
void Foo::Set (int x)
{
x_ = x;
}
main.cpp:
#include "foo.h"
int main ()
{
//Foo foo; <-- error
FooLongNameSpecialisationsParamaters foo;
return 0;
}
No, there is no way to avoid it. Otherwise, how would you know if a given function definition is for a class function or for a static function?
If you are asking if you can define a member function such as Graph::printGraph without specifying the class name qualification, then the answer is no, not the way that you want. This is not possible in C++:
implementation file:
void printEdge(){};
The above will compile just fine, but it won't do what you want. It won't define the member function by the same name within the Graph class. Rather, it will declare and define a new free function called printEdge.
This is good and proper, if by your point of view a bit of a pain, because you just might want two functions with the same name but in different scopes. Consider:
// Header File
class A
{
void foo();
};
class B
{
void foo();
};
void foo();
// Implementation File
void foo()
{
}
Which scope should the definition apply to? C++ does not restrict you from having different functions with the same names in different scopes, so you have to tell the compiler what function you're defining.
//yes it is possible using preprocessor like this:
#define $ ClassName //in .cpp
void $::Method1()
{
}
//or like this: in the header .h:
#undef $
#define $ ClassName'
// but you have to include the class header in last #include in your .cpp:
#include "truc.h"
#include "bidule.h" ...
#include "classname.h"
void $::Method() { }
//i was using also
#define $$ BaseClass
//with single inheritance than i can do this:
void $::Method()
{
$$::Method(); //call base class method
}
//but with a typedef defined into class like this it's better to do this:
class Derived : Base
{
typedef Base $$;
}
EDIT: I misread your question. This would be an answer to the question whether you can split header-files. It doesn't help you to avoid using LongClassName::-syntaxes, sorry.
The simple answer: You can split up c++-file, but you can not split up header-files.
The reason is quite simple. Whenever your compiler needs to compile a constructor, it needs to know exactly how many memory it needs to allocate for such an object.
For example:
class Foo {
double bar; //8 bytes
int goo; //4 bytes
}
new Foo() would require the allocation of 12 bytes memory. But if you were allowed to extend your class definitions over multiple files, and hence split header files, you could easily make a mess of this. Your compiler would never know if you already told it everything about the class, or whether you did not. Different places in your code could have different definitions of your class, leading to either segmentation faults or cryptic compiler errors.
For example:
h1.h:
class Foo {
double bar; // 8 bytes
int goo; // 4 bytes
}
h2.h:
#include "h1.h"
class Foo {
double goo; // 8 bytes
} // we extend foo with a double.
foo1.cpp:
#include "foo1.h"
Foo *makeFoo() {
return new Foo();
}
foo2.cpp:
#include "foo2.h"
void cleanupFoo(Foo *foo) {
delete foo;
}
foo1.h:
#include "h1.h"
Foo *makeFoo();
foo2.h:
#include "h1.h"
#include "h2.h"
void cleanupFoo(Foo *foo)
main.cpp:
#include foo1.h
#include foo2.h
void main() {
Foo *foo = makeFoo();
cleanupFoo(foo);
}
Carefully check what happens if you first compile main.cpp to main.o, then foo1.cpp to foo1.o and foo2.cpp to foo2.o, and finally link all of them together. This should compile, but the makeFoo() allocates something else then the cleanupFoo() deallocated.
So there you have it, feel free to split .cpp-files, but don't split up classes over header files.