I have a bit of code of the following format contained in a single .h and .cc file:
myClass.h:
#ifndef MYCLASS_H
#define MYCLASS_H
class myClass
{
public:
myClass(); // constructor
~myClass(); // destructor
void classMethod1 ();
void classMethod2 ();
int memberVarable1;
int memberVariable2;
};
#endif
and myClass.cc:
#include "myClass.h"
myClass::myClass(){
// stuff
}
myClass::~myClass(){
// stuff
}
void myClass::classMethod1 (){
// stuff
}
void myClass::classMethod2 (){
// stuff
}
All of this is working fine. However my project is getting quite large and I'm about to add a set of new functionality. Instead of clogging up myClass.h and myClass.cc I want to put some new methods in another .cc file. I don't seem to be able to get this to work though.
myClass.h:
#ifndef MYCLASS_H
#define MYCLASS_H
#include "secondFile.h"
class myClass
{
public:
myClass(); // constructor
~myClass(); // destructor
void classMethod1 ();
void classMethod2 ();
int memberVarable1;
int memberVariable2;
};
#endif
and myClass.cc:
#include "myClass.h"
#include "secondFile.h"
myClass::myClass(){
// stuff
}
myClass::~myClass(){
// stuff
}
void myClass::classMethod1 (){
// stuff
}
void myClass::classMethod2 (){
// stuff
}
secondFile.h:
#ifndef SECONDFILE_H
#define SECONDFILE_H
void someNewMethod();
#endif
secondFile.cc
#include "secondFile.h"
void someNewMethod(){
// can't see classMethod1()
}
In every source file, you need to include every header file that declares functions, etc. you want to use.
So in your case, it seems like you want secondFile.cc to contain
#include "myClass.h"
#include "secondFile.h"
void someNewMethod(){
// can't see classMethod1()
}
Btw, what you are doing is quite common to do in practice. Sometimes, I go even further than what you suggest, and implement the various methods of a single class in multiple source files. For large, complicated classes, this helps speed up the development cycle because I only have to recompile a fraction of the class implementation if I only made a small change. Example:
myclass.h
#pragma once
class MyClass
{
...
void complicatedMethod0();
void complicatedMethod1();
...
};
myclass_impl0.cpp
#include "myclass.h"
void MyClass::complicatedMethod0()
{
...
}
myclass_impl1.cpp
#include "myclass.h"
void MyCLass::complicatedMethod1()
{
...
}
If you are intending to add methods to myClass, you can't do that - the class methods have to be contained in one definition.
You can extend myClass, however, by inheriting from it:
secondFile.h:
#ifndef SECONDFILE_H
#define SECONDFILE_H
#include "myClass.h"
class mySecondClass : public myClass
{
public:
void someNewMethod();
}
#endif
secondFile.cc
#include "secondFile.h"
void mySecondClass::someNewMethod(){
this.classMethod1();
}
#include "secondFile.h"
#include "myClass.h"
//if you want the class methods,
//you need to tell the compiler where to look
void someNewMethod(){
// can't see classMethod1()
}
it seems you've forgotten to include "myClass.h".
Related
I am kind of new to C++ (and StackOverflow). I am trying to get something to work, but I have some #include problems.
I want to call a callback I made (from here), but I am struggling to do this.
This is my code so far. When I include child.hpp in the someclass.hpp file (because it needs information about Child for Callback<Child>), it has a looped include and the compiler crashes.
I have read about forward declarations (would be class Child; in the someclass.hpp file), and after trying I figured out this works, but I also read different opinions about this.
I have all .hpp files guarded with #ifndef CLASSNAME #define CLASSNAME ... #endif
Do I need to change my entire design, or what is the best option in my case?
base.hpp
#include "someclass.hpp"
class Base
{
protected:
unique_ptr<SomeClass> someClass;
};
base.cpp
#include "base.hpp"
Base::Base()
{
this->someClass = make_unique<SomeClass>();
}
child.hpp
#include "base.hpp"
class Child : public Base
{
public:
void callbackFunction(std::string data);
unique_ptr<Callback<Child>> callback;
};
child.cpp
#include "child.hpp"
void Child::callbackFunction(std::string data)
{
/*does something*/
}
Child::Child()
{
this->callback = make_unique<Callback<Child>>(this, &Child::callbackFunction);
//I can call this->callback->call(data); here without problems
this->someClass->setCallback(this->callback);
//^^^^^^^^^^^^^^^ == base.someClass
}
someclass.hpp
#include "child.hpp" // < does crash compiler due to loop
//> someclass.hpp uses child.hpp
//> child.hpp uses base.hpp
//> base.hpp uses someclass.hpp
// and thus loop
class SomeClass
{
public:
void someFunction(std::string data);
void setCallback(unique_ptr<Callback<Child>> callback);
unique_ptr<Callback<Child>> callbackInstance;
};
someclass.cpp
//not 100% sure about the type of this parameter
void setCallback(unique_ptr<Callback<Child>> callback)
{
this->callbackInstance = callback;
}
void SomeClass::someFunction(std::string data)
{
//here I want to call this "Child::callbackFunction" which should go like "this->callbackInstance->call(data)" ?
}
also in someclass.hpp
template<class T>
class Callback
{
public:
Callback(T* instance, void (T::*function)(std::string))
{
this->callbackInstance = instance;
this->callback = function;
}
void call(std::string data)
{
(callbackInstance->*callback)(data);
}
private:
T *callbackInstance;
void (T::*callback)(std::string);
};
To solve the mentioned error("expected class-name before '{' token on child.hpp") you should remove the #include "someclass.hpp" from base.hpp and replace it with a forward declaration for class SomeClass as shown below.
base.hpp
#ifndef BASE_H
#define BASE_H
//NO NEED TO INCLUDE someclass.hpp
#include <memory>
class SomeClass;//FORWARD DECLARE SomeClass
class Base
{
std::unique_ptr<SomeClass> someClass;
public:
//add declaration for default constructor
Base();
};
#endif
base.cpp
#include "base.hpp"
#include "someclass.hpp"
//other things here
Base::Base()
{
this->someClass = std::make_unique<SomeClass>();
}
child.hpp
#ifndef CHILD_H
#define CHILD_H
#include "base.hpp"
#include <memory>
#include "someclass.hpp"
class Child : public Base
{
public:
void callbackFunction(std::string data);
std::unique_ptr<Callback<Child>> callback;
//add declaration for default constrcutor
Child();
};
#endif
child.cpp
#include "child.hpp"
void Child::callbackFunction(std::string data){
/*does something*/
}
Child::Child()
{
this->callback = std::make_unique<Callback<Child>>(this, &Child::callbackFunction);
//I can call this->callback->call(data); here without problems
}
someclass.hpp
#ifndef SOMECLASS_H
#define SOMECLASS_H
#include <string>
//REMOVED include child.hpp from here
class SomeClass
{
public:
void someFunction(std::string data);
//I think I need an instance of Callback<Child> here?
};
template<class T>
class Callback
{
public:
Callback(T* instance, void (T::*function)(std::string))
{
this->callbackInstance = instance;
this->callback = function;
}
void call(std::string data)
{
(callbackInstance->*callback)(data);
}
private:
T *callbackInstance;
void (T::*callback)(std::string);
};
#endif
someclass.cpp
#include "someclass.hpp"
void SomeClass::someFunction(std::string data)
{
//here I want to call this "Child::callbackFunction" which should go like "this->callbackInstance->call(data)" ?
}
The above program compiles and executes successfully as can be seen here.
Summary
Some of the changes that i made are listed below:
Removed unnecessary includes
Added declarations for default constructor in child.hpp and base.hpp
Added include guards in all headers.
How can I get one class to run another class' function and vice versa C++?
Example:
main.h (Updated/edited)
#ifndef MAIN_H
#define MAIN_H
#include <iostream>
#include "test.h"
class firstClass
{
public:
void runMe();
};
extern firstClass first;
#endif
main.cpp (Updated/edited)
#include "main.h"
firstClass first;
secondClass second;
void firstClass::runMe()
{
std::cout << "I\'m in firstClass\n";
}
int main()
{
second.runMe(); // should output "I'm in secondClass" then "I'm in firstClass"
return 0;
}
test.h (Updated/edited)
#ifndef TEST_H
#define TEST_H
#include <iostream>
#include "main.h"
class secondClass
{
public:
void runMe();
};
extern secondClass second;
#endif
test.cpp (Updated/edited)
#include "test.h"
firstClass first;
secondClass second;
void secondClass::runMe()
{
std::cout << "I\'m in secondClass\n";
first.runMe(); // Now we output the other classs runMe, saying "I'm in firstClass"
}
I really need help, and badly!
I'm self taught and really need this program to work, its for a friend who needs it soon.
Edit: I changed the code, and now I get
/tmp/test-034790.o:(.bss+0x1): multiple definition of `first'
/tmp/main-097c28.o:(.bss+0x1): first defined here
/tmp/test-034790.o:(.bss+0x2): multiple definition of `second'
/tmp/main-097c28.o:(.bss+0x2): first defined here
This is my EngineIncludes.h file:
#include <stdafx.h>
//Engine Includes
namespace Engine
{
//Classes: 23
class BaseObject;
class Console;
class Engine;
class Node;
template <class T> class Transform;
}
#include "core/BaseObject.h"
#include "core/Console.h"
#include "core/Engine.h"
#include "math/Transform.h"
#include "scene/Node.h"
//Global Objects
extern Engine::Console* CONSOLE;
extern Engine::Engine* CORE_ENGINE;
In stdafx.h I have regular stuff like OpenGL, std::map, boost... and I'm building a precompiled header as standard.
This is the Node.h file:
#ifndef _NODE_H
#define _NODE_H
#include <stdafx.h>
#include <EngineIncludes.h>
namespace Engine
{
class Node : public BaseObject
{
public:
Node();
~Node();
void SetParent(Node* parent);
Node* GetParent();
void SetTransform(const Transform<double> &transform);
Transform<double> GetTransform();
Transform<double> GetDerivedTransform();
Transform<double> GetInheritedTransform();
void Update();
private:
Transform<float> transform;
Transform<float> derived;
Node* parent;
};
}
#endif _NODE_H
I get 3 errors here. One C2504 that Engine::BaseObject is not defined. And two C2079 that both Transform transform and Transform use undefined class. Now this is the BaseObject.h:
#ifndef _BASE_OBJECT_H
#define _BASE_OBJECT_H
#include "stdafx.h"
#include "EngineIncludes.h"
namespace Engine
{
class BaseObject
{
public:
BaseObject()
{
id = CORE_ENGINE->GenerateID();
}
~BaseObject()
{
}
long GetID()
{
return id;
}
private:
long id;
};
}
#endif _BASE_OBJECT_H
Now I specifically fully defined BaseObject inside header file with no luck. Still the same error. But if I comment out forward declarations in EngineIncludes.h, the compiler freaks out with
extern Engine::Console* CONSOLE;
It literally ignores all #includes for whatever reason. I've never had an issue like this before. And I tried everything. I even created EngineIncludes.cpp file. I moved the contents of EngineIncludes.h into stdafx.h with no luck. It somehow just ignores #includes. Even if I put #include "BaseObject.h" inside "Node.h" nothing changes. When it compiles Node it has both Transform which is a template class and BaseObject undefined, even though both objects are clearly defined before Node with forward declarations and #includes.
I'm using Visual Studio 2010, but never had an issue like this. I looked into my previous projects and all is written the same fashion and works without problem.
Aaand im back again with my second question and im kinda not sure about wether i should have posted all the seperate classes cuz it looks somewhat long. And im sure the solution is pretty small.
Anyways, i am at polymorphism tutorial vid that i am following and everything works fine if i follow it and put all classes in "main.cpp". But when i tried to do the same program with seperate classes (seen below) i am getting error "
E:\Codeblocks\Poly\main.cpp|11|error: cannot convert 'Ninja' to 'Enemy*' in initialization|".*
I kinda understand what the error is saying..i think.. but dont know what i did wrong since the same code was working when Enemy and Ninja class wasnt seperate but now as seperate classes its not working. I think i included those classes properly in main.cpp.
main.cpp
#include <iostream>
#include "Enemy.h"
#include "Ninja.h"
#include "Monster.h"
int main()
{
Ninja n;
Monster m;
Enemy *enemy1=&n;
Enemy *enemy2=&m;
enemy1->setAttackPower(20);
enemy2->setAttackPower(50);
n.attack();
m.attack();
return 0;
}
Enemy.h
#ifndef ENEMY_H
#define ENEMY_H
class Enemy
{
public:
Enemy();
void setAttackPower(int a);
protected:
int attackPower;
private:
};
#endif // ENEMY_H
Enemy.cpp
#include "Enemy.h"
Enemy::Enemy()
{
//ctor
}
void Enemy::setAttackPower(int a)
{
attackPower=a;
};
Ninja.h
#ifndef NINJA_H
#define NINJA_H
class Ninja
{
public:
Ninja();
void attack();
protected:
private:
};
#endif // NINJA_H
Ninja.cpp
#include "Ninja.h"
#include <iostream>
Ninja::Ninja()
{
//ctor
}
void Ninja::attack(){
std::cout<<" I am a ninja. Ninja chop! -"<<attackPower<<"\n";}
This is because your Ninja class is not inhereted from Enemy class. You must define Ninja class like this:
#include "Enemy.h"
class Ninja : public Enemy
{
public:
Ninja();
void attack();
protected:
private:
};
EDIT: I added #include directive. Without it compiler won't know, where to find Enemy class declaration.
I have a parametrized class Queue and a subclass ClientsQueue not parametrized that inherits from Queue. I think I have a syntax error:
client.h
#ifndef CLIENT_H_
#define CLIENT_H_
class Client {
public:
Client();
~Client();
};
#endif
queue.h
#ifndef QUEUE_H_
#define QUEUE_H_
template <class T> class Queue {
public:
Queue();
~Queue();
};
#endif
clientsQueue.h
#ifndef CLIENTSQUEUE_H_
#define CLIENTSQUEUE_H_
#include "queue.h"
#include "client.h"
class ClientsQueue: public Queue<Client> {
public:
ClientsQueue();
~ClientsQueue();
};
#endif
clientsQueue.cpp
#include "clientsQueue.h"
ClientsQueue::ClientsQueue() {
};
bank.cpp
#include "clientsQueue.cpp"
int main() {
return 0;
}
So, when I try to compile and run the program, the compiler says:
clientsQueue.cpp:3:1: error: ‘ClientsQueue’ does not name a type
ClientsQueue::ClientsQueue() {
^
I can't see the error. If I quit all the code from clientsQueue.cpp, it works.
How can I fix it?
Thanks!
You should #include "clientsQueue.h" not #include "clientsQueue.cpp" in main file. When you include header you present a declarations to the compiler. You miss the declaration of the class ClientsQueue when you include just the source (cpp) file.