This might me a silly problem. But I am not getting the conceptual problem in the program.
I want to pass the pointer of class Child in a global function and access that pointer object from different parts of the project just by including Child.h
Problem: the following problem does not work when I do get_Child()->number_1 in the main.
Solution: if I include the Child.cpp in the main, and inline the Constructor or
if I declare the constructor in the Child.h instead of Child.cpp
Query request. What is the reason for this behavior? A way how I can declare the Constructor in Child.cpp and does not have to include Child.cpp in the main.cpp
main.cpp
#include <iostream>
#include "Child.h"
//#include "Child.cpp"
using namespace std;
int main(){
Child *pC = new Child();
cout << "direct = " << pC->number_1 << endl;
cout << "with function = " << get_Child()->number_1 << endl;
}
Child.h
#ifndef CHILD_H_
#define CHILD_H_
class Child;
static Child * pointer_Child;
inline void save_Child(Child * p_C){
pointer_Child = p_C;
}
inline Child * get_Child(){
return pointer_Child;
}
class Child {
public:
Child();
//Child(){
// this ->set_Child();
//}
void set_Child(){
save_Child(this);
}
int number_1 = 10;
};
#endif /* CHILD_H_ */
Child.cpp
#include "Child.h"
//inline Child::Child(){
// this ->set_Child();
//}
Child::Child(){
this->set_Child();
}
Do not declare static variables in a header (outside of classes) like this:
static Child * pointer_Child;
It will create a variable in every compilation unit that includes the header. And they are not accessible from outside the translation unit.
Instead, make pointer_Child extern and provide an implementation in the CPP as follows:
Header:
extern Child* pointer_Child;
CPP:
Child* pointer_Child;
And never include a CPP file.
Related
I'm sort of new to C++, and I've been making my way through a bit in my own project. I ran into an error with this header and .cpp file
// main.cpp
#include <iostream>
#include "Header.h"
int main() {
MyClass::TestFunction(); //'MyClass::TestFunction': illegal call of non-static member function
}
// header.h
#ifndef HEADER_H
#define HEADER_H
#include <iostream>
class MyClass {
public:
void TestFunction() {
std::cout << "Hello World\n"; //Where I beleive the issue is
}
};
#endif
Now I think the issue comes from std::cout not being static and the declaration in main.cpp needs it to be static, but I'm not sure how to make it static so that main.cpp works correctly. If anyone could give me a tip as to how I can make things like this work later on down the road, that would be awesome :)
the issue comes from std::cout not being static and the declaration in main.cpp needs it to be static
You either have to make your function static OR to intanciate an object of your class and hen call its function :
main.cpp
int main() {
MyClass pony;
pony.TestFunction();
}
OR
header.h
class MyClass {
public:
static void TestFunction() {
std::cout << "Hello World\n";
}
};
whenever a member function is written inside a class, it can be called only using object. You have to create a object in main function.
// main.cpp
#include <iostream>
#include "header.h"
int main() {
MyClass myObject;
myObject.TestFunction(); //'MyClass::TestFunction': illegal call of non-static member function }
OR
If you dont want to use object, then make the member function as static.
// header.h
#ifndef HEADER_H
#define HEADER_H
#include <iostream>
class MyClass { public:
void static TestFunction() {
std::cout << "Hello World\n"; //Where I beleive the issue is
} };
#endif
Ive been using c++ for some months now but Ive come across an error when I use header and source code files. I create a source code file
that contains a class gun(example not actual program):
class gun
{
private:
int stuff;
public:
void doStuff();
};
void Gun::doStuff()
{
cout << stuff << endl;
}
and then i created a header file and declared the class like this:
class gun;
then in my main source file i do this:
int main()
{
gun *mygun = new gun;
mygun->doStuff();
return 0;
}
however when i try to execute it i get the error:
invalid use of incomplete type 'class gun' and i think the problem is how i declared it in the header, did i do it wrong? how was i meant to do it? thanks.
Thanks Everyone that helped! I understand now, i thought that only the forward declaration
went into the header file, thanks for all your answers!
You seem to be going about seperating the implementation and header file the wrong way. Forward declarations should not go in the header file. The entire declaration should! This is how your code should be structured
Gun.hpp
#pragma once
class Gun
{
private:
int stuff;
public:
void doStuff();
};
Gun.cpp
#include "Gun.hpp"
#include <iostream>
using std::cout;
using std::endl;
void Gun::doStuff()
{
cout << stuff << endl;
}
main.cpp
int main()
{
Gun *mygun = new Gun;
mygun->doStuff();
delete mygun; // <-- remember this!
return 0;
}
the separation of header and implementation is crucial in C++ and other languages! You should only declare the class in the header along with its full interface (as above) and include all implementation details in the .cpp file (as above :)
The entire declaration of the gun class needs to be in the header file. What you declared in the header file is a forward declaration, which is not enough by itself to create an instance of the class. Forward declarations are useful for allowing other code to declare pointers only, since the compiler does not need to know the full details just to declare a pointer. But a forward declaration can't be used for creating actual object instances of the class. That is why you are getting errors about an incomplete type. From main()'s perspective, it has no idea what gun actually looks like, so it can't create a full instance of it.
The implementation of the methods for the gun class needs to be in the gun's source file, which can #include the header file to validate and access the class members.
gun.h
#ifndef gun_h
#define gun_h
class gun
{
private:
int stuff;
public:
void doStuff();
};
#endif
gun.cpp
#include "gun.h"
#include <iostream>
void gun::doStuff()
{
std::cout << stuff << std::endl;
}
Now, in main() (or any other source file), you can #include the header file and use the class as needed:
#include "gun.h"
int main()
{
gun *mygun = new gun;
mygun->doStuff();
delete mygun;
return 0;
}
In gun.h
#ifndef GUN_H_
#define GUN_H_
// You can use #pragma once too here
class gun
{
private:
int stuff;
public:
void doStuff();
};
#endif
In gun.cpp file
#include "gun.h"
void gun::doStuff()
{
cout << stuff << endl;
}
and then main.cpp
#include "gun.h"
int main() {
//your code using the class
gun *mygun = new gun;
mygun->doStuff();
return 0;
}
and you can compile and test using
g++ -o prg_name gun.cpp main.cpp && ./prg_name
I checked several answers on the forums about this topic, but for some reason I still cannot wrap my mind about the problem and get my works running.
My aim is to have one object of a class available in all translation units. Note, I do not seek to implement a singleton pattern here. There can be multiple instances of the class, but there will always be at least one and this one can be seen where "its header" is included.
Assume a design like this:
---logging.h---
class LogCenter {
...
}
class Logger {
private:
LogCenter& center;
public:
Logger(); //automatically assigns the ominous global LogCenter object (reference) to center.
Logger(LogCenter&); //however, any other LogCenter object would work equally fine.
}
The reason? I want that all Loggers can use this global LogCenter per default, wherever they may be used.
But now I'm unsure how to provide this global LogCenter. It has the default constructor. Do I just add a line extern LogCenter globalCenter; into the logging.h file and another LogCenter globalCenter; line into the logging.cpp file? Or just LogCenter globalCenter; in the logging.cpp and extern LogCenter globalCenter; in any file that uses it?
I am really confused, none of which I tried worked - however, the overall code works fine when I use the constructor overload with its own LogCenter instance.
EDIT: Important: extern goes with declaration (e.g. in header file). Then one single definition in an implementation file.
Check all the answers!
This is how it works:
---logging.h---
class Entry;
class LogCenter {
friend class Logger; //please don't bash my friend design right away... D:
private:
list<Entry> entries;
public:
void printLog(string file);
}
extern LogCenter SCenter;
class Logger {
private:
LogCenter& center;
public:
Logger(); //uses extern or "singleton" object.
Logger(LogCenter&);
void commitEntry(Entry); //adds the Entry object to the list in the center object.
}
-----------------
---logging.cpp---
#include "logging.h"
LogCenter SCenter;
void Logger::commitEntry(Entry e) {
entries.push_back(e); //Logger can access LogCenter fields!
}
void LogCenter::printLog(string file) {
//open file stream str
for(list<Entry>::iterator it = entries.begin();...)
str << it->getEntry() << endl;
//close file
}
--------------
---main.cpp---
#include "logging.h"
int main() {
Logger log;
Entry e("Some entry");
log.commitEntry(e);
SCenter.printLog("filename.log");
//or
LogCenter cent;
Logger log(cent);
Entry e("some entry");
log.commitEntry(e);
cent.printLog("filename.log");
return 0;
}
-------------
Using an extern variable is one option.
Another option is to have a function that returns a reference.
logging.h:
LogCenter& getGlobalLogCenter();
logging.cpp:
LogCenter& getGlobalLogCenter()
{
static LogCenter lc;
return lc;
}
//logcenter.h
#ifndef LOGCENTER_H_
#define LOGCENTER_H_
class LogCenter {
private:
int dummy;
public:
int getVal(){ return dummy; };
LogCenter() : dummy(0){};
LogCenter(int val) : dummy(val) {};
};
#endif // LOGCENTER_H_
xxx
// logcenter.cpp
#include "LogCenter.h"
LogCenter globalCenter;
xxx
//logger.h
#ifndef LOGGER_H_
#define LOGGER_H_
#include <string>
#include "LogCenter.h"
class Logger {
private:
LogCenter& center;
public:
Logger(); //automatically assigns the ominous global LogCenter object (reference) to center.
Logger(LogCenter&); //however, any other LogCenter object would work equally fine.
std::string print() { return std::string("This class uses logger ") + std::to_string(center.getVal()); };
};
#endif // LOGCENTER_H
xxx
// logger.cpp
#include "Logger.h"
extern LogCenter globalCenter;
Logger::Logger() : center(globalCenter) {};
Logger::Logger(LogCenter &logcenter) : center(logcenter) {};
xxx
// main.cpp
#include "Logger.h"
int main(int argc, char* argv[])
{
LogCenter logcenter2(2), logcenter3(3);
Logger logger1, logger2(logcenter2), logger3(logcenter3);
std::cout << logger1.print() << std::endl;
std::cout << logger2.print() << std::endl;
std::cout << logger3.print() << std::endl;
return 0;
}
output is:
This class uses logger 0
This class uses logger 2
This class uses logger 3
I recommend you to use the following C++ singleton pattern which is easy to use and even safe when using it across shared libraries:
// LogCenter.h
class /*API_MACRO_FOR_EXPORTING*/ LogCenter {
public:
static LogCenter* instance();
}
// For quick access you could define a macro
#define sLogCenter \
LogCenter::instance()
// LogCenter.cpp
LogCenter* LogCenter::instance()
{
static LogCenter instance;
return &instance;
}
// LogCenter::instance()->DoSomething();
// sLogCenter->DoSomething();
To answer your question about extern:
// LogCenter.h
// You can use multiple definitions with extern so the compiler
// knows the LogCenter is instantiated somewhere else.
extern LogCenter globalCenter;
// LogCenter.cpp
// Only 1 declaration of LogCenter
/*API_MACRO_FOR_EXPORTING*/ LogCenter globalCenter;
I would go with the second option, that is, "extern LogCenter globalCenter;" in the file where ever it is used.
The reason, if someone is including logging.h, may be for creating the new object of Logcenter class, but does not intend to use the globalCenter object, then why he needs the extern declaration for globalCenter object.
Trying to pass a parent class object to a child class object so that the child class object has control over the parent class object's methods.
This is however resulting in header related issues.
I've tried forward declaring one of the classes but it seems whatever class is declared first always has trouble reading from the class declared below.
Both errors refer to Device' constructor where try to call dm's hello world method, they are:
Use of undefined type 'DeviceManager'
Left of '->HelloWorld' must point to class/struct/union/generic type
...
//main.cpp
#include "parent.h"
void main()
{
cout << "Created DeviceManager\n";
DeviceManager* deviceManager = 0;
deviceManager = new DeviceManager;
cout << "Giving DeviceManager a device\n";
deviceManager->p = new Device(deviceManager);
cout << "Giving Device a reference to DevicenManager\n";
deviceManager->Share();
}
...
class DeviceManager;
class Device
{
public:
Device(DeviceManager* manager)
{
dm = 0;
this->dm = manager;
this->dm->HelloWorld();
}
DeviceManager* dm;
};
//device manager
class DeviceManager
{
public:
DeviceManager()
{
p = 0;
}
void HelloWorld()
{
//if this calls we know the child has control over the parent.
cout << "Hello World";
}
Device* p;
};
Yes.
To solve circular dependencies with class member and function declarations, you can forward-declare a class:
class A;
class B {
A *a;
};
class A {
B *b;
};
To define class member functions that access members of the other class, you must define the function after the other class has been defined:
class B;
class A {
public:
void f(B &arg);
};
class B {
public:
void g(A &arg);
};
void A::f(B &arg) {
arg.g(*this);
}
void B::g(A &arg) {
arg.f(*this);
}
Usually, in a C++ project, you wouldn't even encounter this problem: You would put function definitions, i.e. implementations, into .cpp files, while putting the class definitions into header files. Class forward declarations, if neccesary, could be put into their own header files that are included by all headers that need them.
A full example of how you would split the above code into multiple files:
a.cpp
#include "a.h"
#include "b.h"
void A::f(B &arg) {
arg.g(*this);
}
b.cpp
#include "b.h"
#include "a.h"
void B::g(A &arg) {
arg.f(*this);
}
a.h
#ifndef _A_H_
#define _A_H_
#include "forward_declarations.h"
class A {
public:
void f(B &arg);
};
#endif //_A_H_
b.h
#ifndef _B_H_
#define _B_H_
#include "forward_declarations.h"
class B {
public:
void g(A &arg);
};
#endif //_B_H_
forward_declarations.h
#ifndef _FORWARD_DECLARATIONS_H_
#define _FORWARD_DECLARATIONS_H_
class A;
class B;
#endif //_FORWARD_DECLARATIONS_H_
As a general rule of thumb, if you need to forward-declare a class, you might have misdesigned something and should think about whether there is a better way (but there also are perfectly valid use cases that require class forward declarations).
If you don't understand my #ifndef, #define and #endif preprocessor lines: These are header guards, and should be used with all files that are included somewhere else, exception you know precisely what you're doing. Believe me. You'll regret ommiting one.
If your problem is cyclic dependancy, like this:
// DeviceManager.h
#include "device.h"
class DeviceManager
{
DeviceManager(Device& device) {}
};
// Device.h
#include "DeviceManager.h"
class Device
{
Device(DeviceManager& manager) {}
};
You can solve the problem be forward declaring one of the classes, and passing the object by pointer.
// Device.h
//#include "DeviceManager.h"
class DeviceManager;
class Device
{
Device(DeviceManager* manager) {}
};
I have a templated class Child which inherits from a non-templated Parent class. When I include Child's header in multiple .cpp files I get a LNK2005 error. This happens because Parent gets defined in multiple compilation units. When those units get linked together they cause the LNK2005 error.
In case you're wondering, the purpose of Parent is to give Child one static variable for all Child instance, not just one for each Child< ''type'' >.
My question is, how do I create a templated class which has a unique (across all Child instances) static variable and can be included in multiple .cpp files?
Here's a toy example that causes this LNK2005 error:
main.cpp
#include "Apple.h"
#include "Banana.h"
#include <string>
void main() {
Apple apple;
Banana banana;
}
Apple.h
#ifndef APPLE_H
#define APPLE_H
struct Apple {
Apple();
};
#endif // APPLE_H
Apple.cpp
#include "Apple.h"
#include "Child.h"
Apple::Apple() {
Child<int> child;
child.foo(5);
}
Banana.h
#ifndef BANANA_H
#define BANANA_H
struct Banana {
Banana();
};
#endif // BANANA_H
Banana.cpp
#include "Banana.h"
#include "Child.h"
Banana::Banana() {
Child<double> child;
child.foo(3.14);
}
Child.h
#ifndef CHILD_H
#define CHILD_H
#include <iostream>
using namespace std;
///////////// Parent Class Def ///////////
class Parent {
protected:
static int id;
};
int Parent::id = 0;
///////////// Child Class Def ///////////
template <class T>
struct Child : protected Parent {
Child();
void foo(T t);
};
template <class T>
Child<T>::Child() {
id++;
}
template <class T>
void Child<T>::foo(T t) {
cout << "Child" << id << "'s foo() says: " << t << endl;
}
#endif // CHILD_H
error LNK2005: "protected: static int Parent::id" (?id#Parent##1HA) already defined in Apple.obj
You need to define int Parent::id = 0; just once in Child.C. By including it in the header it gets defined once per file that includes your header.
I suppose I should note that between the evils of putting it in Parent.C (matching class name) or Child.C matching the header name, I picked consistency. Much better is to put Parent in its own files so that you can put the definition in an aptly named Parent.C which still matches the corresponding header name.
Pull
int Parent::id = 0;
out into Parent.cpp and you 'll be fine. What happens now is that the definition gets included once per translation unit that includes Child.h.