C++ Inheritance in Separate Files Using #include and Inclusion Guards - c++

I am new to Stack Overflow and am teaching myself C++, but am still quite a beginner. After completing a nice chunk of the book I am using (which may be considered out dated and/or not a great book) I decided to re-enforce some concepts by trying them on my own, referencing the book only if needed, but I appear to be stuck. The concepts I am trying to tackle are inheritance, polymorphism, abstract data types (ADT), and separating the code for my classes into header files (.h) and C++ file (.cpp). Sorry in advance for the wall of text, I just want to be clear and specific where I need to be.
So, my goal is to create simple shape classes that inherit from one another where applicable. I have four classes: myPoly, myRectangle, myTriangle, and mySquare. myPoly, if I understood this concept correctly, should be an ADT since one of the methods is a pure virtual function (area method), since creating a myPoly object isn't something I would want a user of my classes to do. myRectangle and myTriangle both derive from myPoly and in turn mySquare derives from myRectangle. I've also included my test program where I planned on testing my classes. I am using Code::Blocks 10.05 and keep getting the following error when I build my test.cpp program:
undefined reference to 'myPoly::myPoly()'
I get 42 similar errors all for the methods of the myPoly class. This happens when I try to build the .cpp files for myRectangle and myTriangle too. With the research I tried to do on the problems I been running into with this little project I feel like something is wrong with my inclusion guards or my #include statements, and something isn't getting included properly or is getting included too many times. At first I was providing the .cpp file for myPoly to myRectangle and myTriangle, but read in a couple of places that including the .h file for myPoly is more efficient and some how automatically include its .cpp. If anyone can provide some insight on that, it would be greatly appreciated. I also remember something about how using quotes in your inclusion statements is different than using the angle brackets. Below are all nine files that I have made for my little project. Most of the comments are little notes or reminders to me.
myPoly.h
//Practice with inheritance, polymorphism, and Abstract Data Types
//header file for Polygon class
#ifndef MYPOLY_H
#define MYPOLY_H
class myPoly
{
public:
//constructor
//const reference pass because the values w and h don't change and reference avoid the time it takes to copy large
// objects by value (if there were any)
myPoly();
myPoly(const float & w, const float & h);
//destructor
virtual ~myPoly();
//accessors
float getWidth();
float getHeight();
void setWidth(const float & w);
void setHeight(const float & h);
virtual float area() = 0;
private:
float width, height;
};
#endif
myPoly.cpp
//Practice with inheritance, polymorphism, and Abstract Data Types
//implementation file for myPoly class
#include "myPoly.h"
//constructor
myPoly::myPoly()
{
setWidth(10);
setHeight(10);
}
myPoly::myPoly(const float & w, const float & h)
{
setWidth(w);
setHeight(h);
}
//destructor
myPoly::~myPoly() {}
//accessors
float myPoly::getWidth() {return width;}
float myPoly::getHeight() {return height;}
void myPoly::setHeight(const float & w) {width = w;}
void myPoly::setWidth(const float & h) {height = h;}
//pure virtual functions have no implementation
//area() is handled in the header file
myRectangle.h
//Practice with inheritance, polymorphism, and Abstract Data Types
//declaration file for myRectangle class
#ifndef MYRECTANGLE_H
#define MYRECTANGLE_H
#include "myPoly.h"
class myRectangle : public myPoly
{
public:
//constructor
myRectangle();
myRectangle(const float & w, const float & h);
//destructor
~myRectangle();
//this doesn't need to be virtual since the derived class doesn't override this method
float area();
};
#endif
myRectangle.cpp
//Practice with inheritance, polymorphism, and Abstract Data Types
//implementaion file for the myRectangle class
//get a vauge compiler/linker error if you have virtual methods that aren't implemented (even if it ends up being just
// a 'stub' method, aka empty, like the destructor)
#include "myRectangle.h"
myRectangle::myRectangle()
{
setWidth(10);
setHeight(10);
}
myRectangle::myRectangle(const float & w, const float & h)
{
setWidth(w);
setHeight(h);
}
myRectangle::~myRectangle()
{
}
float myRectangle::area()
{
return getWidth() * getHeight();
}
myTriangle.h
//Practice with inheritance, polymorphism, and Abstract Data Types
//declaration file for myTriangle class
#ifndef MYTRIANGLE_H
#define MYTRIANGLE_H
#include "myPoly.h"
//imagine the triangle is a right triangle with a width and a height
// |\
// | \
// | \
// |___\
class myTriangle : public myPoly
{
public:
//constructors
myTriangle();
myTriangle(const float & w, const float & h);
//destructor
~myTriangle();
//since nothing derives from this class it doesn't need to be virtual and in turn neither does the destructor
float area();
};
#endif
myTriangle.cpp
//Practice with inheritance, polymorphism, and Abstract Data Types
//implementation file for myTriangle class
#include "myTriangle.h"
myTriangle::myTriangle()
{
setWidth(10);
setHeight(10);
}
myTriangle::myTriangle(const float & w, const float & h)
{
setWidth(w);
setHeight(h);
}
myTriangle::~myTriangle()
{
}
float myTriangle::area()
{
return getWidth() * getHeight() / 2;
}
mySquare.h
//Practice with inheritance, polymorphism, and Abstract Data Types
//declaration file for mySquare class
#ifndef MYSQUARE_H
#define MYSQUARE_H
#include "myRectangle.cpp"
class mySquare : public myRectangle
{
public:
//constructors
mySquare();
//explicity call the myRectangle constructor within this implementation to pass w as width and height
mySquare(const float w);
//destructor
~mySquare();
};
#endif
mySquare.cpp
//Practice with inheritance, polymorphism, and Abstract Data Types
//implementation file for mySquare class
#include "mySquare.h"
mySquare::mySquare()
{
setWidth(10);
setHeight(10);
}
mySquare::mySquare(const float w)
{
myRectangle::myRectangle(w, w);
}
mySquare::~mySquare()
{
}
test.cpp
//Practice with inheritance, polymorphism, and Abstract Data Types
//main class that uses my shape classes and experiments with inheritance, polymorphism, and ADTs
#include "myRectangle.cpp"
//#include "mySquare.cpp"
#include "myTriangle.cpp"
#include <iostream>
int main()
{
myPoly * shape = new myRectangle(20,20);
return 0;
}
I am very curious as to why I am getting these errors or why something I did may not be considered good/best practice, as opposed to just receiving a line of code to make my errors go away.

Your inclusion guards look fine. If they were not, you would most likely get a compiler error, including file and line number information. The error you posted seems more like a linker error.
However, there is one "problem" with your code. As a general rule, you should only #include .h files and not .cpp files.
Now to get to the solution: I am unfamiliar with Code::Blocks myself. However, I hope I can give some general information that will point you in the right direction. Some compilers I have used in the past by default allowed me to compile a single C++ file and run the program. To compile a program with more than one file, I had to create a project. (Most modern compilers force you to create a project from the start.) With this in mind, I would suggest you check out how to create a project for your program in Code::Blocks.

From a code stand point (at least what I looked through), it looks pretty good, but:
There are two things to consider:
Don't directly include cpp files. For example, in mySquare.h, #include "myRectangle.cpp" should be #include "myRectangle.h". You want to be including the interface/declarations provided in the header file that tell the program how to make the class, not just the function definitions.
Second, make sure you're compiling with all your object files. I don't know code blocks, but if you were using g++ or something like that, you'd want to do g++ main.cpp myPoly.cpp mySquare.cpp etc. for all files. An error like this may happen if you forget myPoly.cpp, for example, because no definitions for its functions would be included.

Everything looks fine, actually. It is probably just as simple as not including myPoly.obj when you link your program. I am not familiar with Code::Blocks (although I know it's fairly popular) but I assume if you just, for example, click on test.cpp and choose "Run", that Code::Blocks will try to build a program from just that one source file. You'll need to include all the relevant source files in each program that you build.

Additionally to what the otehr guys said: You are not doing inheritance right...
When you do
class Poly
{
Poly();
~Poly();
}
class Rect : public Poly()
{
Rect();
~Rect();
}
You need to declare the child's constructor the following way:
Rect::Rect() : Poly()
{
}
The child must only be constructed after the father has finished constructing.

Related

"Expected Class name" Error for Inheritance

Problem
Currently designing a GUI game, and I've finished the basic OOP aspects of the game(along with 90% of all non-abstract classes). However, I tried extending a class called Protester to this class which caused the error at line 5 here:
#ifndef HardcoreProtester_h
#define HardcoreProtester_h
#include "Protester.h"
class HardcoreProtester : public Protester{
public:
HardcoreProtester(StudentWorld* w, int x, int y) : Protester(w, x, y, IID_HARD_CORE_PROTESTER, 20){};
private:
};
#endif /* HardcoreProtester_h */
when extending from this
#ifndef Protester_h
#define Protester_h
#include "Actor.h"
#include "StudentWorld.h"
class Protester : public Human{
static const int INIT_PERP_TICK = 200;
static const int DAMAGE = 20;
static const int SHOUT_WAIT = 25;
static const int MIN_STEP = 8;
static const int MAX_STEP = 60;
static const int EXIT_X = 60;
static const int EXIT_Y = 60;
public:
static const int INIT_HITPOINTS = 5;
Protester(StudentWorld* w, int startX, int startY, int ID, int hp);
virtual ~Protester();
virtual void doSomething();
Direction pickRandomDirection();
virtual bool changeState(Direction dir);
virtual bool isDead() const{
return Human::isDead() && getX() == 60 && getY() == 60;
}
virtual bool isDeadState() const{
return Human::isDead();
}
virtual void consume();
virtual void setDead();
virtual bool moveDelta(StudentWorld* world, Direction dir, int& xdir, int& ydir, int steps = 1);
int determineRandomSteps();
bool canTurn(Actor::Direction dir);
Actor::Direction randTurn(Actor::Direction dir);
Actor::Direction oppositeDir(Actor::Direction dir);
Actor::Direction numToDir(int num);
private:
int step;
int restTick;
int shoutTick;
int perpTick;
};
#endif /* Protester_h */
I've looked on stack overflow for answers to why the error persists, and I've tried to break a nonexistent circular dependency (as you can see Protester does not even include HardcoreProtester). I tried to break any circular dependency by adding a
class Protester;
above the definition of HardcoreProtester.
However, this gives me the error:
Type 'Protester' is not a direct or virtual base of 'HardcoreProtester'
and
Base class has incomplete type
I also made sure the base class is not abstract(I was able to initialize it without any errors).
If this isn't enough information, here's the github for the project:
https://github.com/OneRaynyDay/FrackMan
I apologize for any ambiguity in my question - I just simply have no idea where the error could be(hence an attempt for MCVE with github link). Thanks in advance!
EDIT: Also, using XCode to make this project. By this point into debugging I'm starting to suspect XCode of being the culprit.
In addition, just to be extra helpful and verifiable, here's a picture of the error diagnosis from XCode:
No, XCode is not the culprit. It's not XCode's fault that you have circular header dependencies.
According to the compiler dump you posted, it appears that your StudentWorld.h header file has a #include of HardProtester.h.
This is a case of classical circular header dependencies.
First, you are including Protester.h.
Before Protester.h even gets to its definition of the Protester class, it has an #include of StudentWorld.h.
StudentWorld.h must have an #include of HardProtester.h, according to your compiler's error diagnostics.
Now, your HardProtester.h has it's own include of Protester.h. But, because its ifndef/define guard has already been set, in the first include of Protester.h, the second #include of this header file becomes empty text.
And now, upon returning to HardProtester.h, you attempt to declare it's class.
Now, if you have been paying attention carefully, you should've figured out that the Protester class has not yet been declared, yet this header file attempts to declare its subclass.
There's your problem. You need to completely refactor how your header files depend on each other, to eliminate this circular dependency. Merely sticking a "class Protester" in HardProtester.h is insufficient. The entire class must be defined, not just declared, before you can declare any subclasses.
You have a circular dependency between Protester.h and StudentWorld.h
Try fixing that and see if it helps.

How do I override in C++?

I can't get method overriding to work. Right now I have a class called Sprite, and two subclasses; Let's call them Goomba and Koopa. Instances of Koopas and Goombas are stored in an std::list of sprites called spriteList, and an iterator goes through this list and calls each sprite's behave() function.
I can get this to work with Goombas alone, by defining the behavior function as Sprite::behave(). But if I try to do the same thing with Koopas, the compiler gets mad because Sprite::behave() is already defined in Goomba. What am I doing wrong? I get the feeling that the answer is an extremely simple syntax issue, but looking online yielded no examples that looked quite like my code.
I'll paste some code, hopefully it'll help. This isn't my exact source code, so I apologize for any typos.
//Sprite.h:
#ifndef SPRITE_H
#define SPRITE_H
class Sprite {
private:
float xPosition; float yPosition;
public:
Sprite(float xp, float yp);
void move(float x, float y); //this one is defined in Sprite.cpp
void behave(); //this one is NOT defined in Sprite.cpp
};
#endif
//Goomba.h:
#ifndef GOOMBA_H
#define GOOMBA_H
#include "Sprite.h"
class Goomba : public Sprite {
public:
Goomba(float xp, float yp);
void behave();
};
#endif
//Goomba.cpp:
#include "Goomba.h"
Goomba::Goomba(float xp, float yp): Enemy(xp, yp) {}
void Sprite::behave(){
Sprite::move(1, 0);
}
//Koopa.h looks just like Goomba.h
//Koopa.cpp
#include "Koopa.h"
Koopa::Koopa(float xp, float yp): Enemy(xp, yp) {}
void Sprite::behave(){
Sprite::move(-2, 1);
}
In Sprite you have to declare the function as virtual
virtual void behave();
Then in Goomba you should state that you are going to override that function
virtual void behave() override;
Note: The override keyword is new as of C++11
In both Koopa.cpp and Goomba.cpp you are defining Sprite::behave. This results in two definitions, as your toolchain told you. You want to define Koopa::behave and Goomba::behave, respectively, in those files.
You also want to define Sprite::behave in Sprite.cpp (you said you currently do not define it anywhere).
You will also want to make Sprite::behave a virtual function in order to get the polymorphic behavior you are after working the way you likely expect it to:
class Sprite {
// ...
// You can either define Sprite::behave in Sprite.cpp or change the declaration to:
// virtual void behave() = 0;
// to make it "pure virtual," indicating that subclasses must provide an implementation.
virtual void behave();
};
In Goomba.cpp, for example:
#include "Goomba.h"
Goomba::Goomba(float xp, float yp): Enemy(xp, yp) {}
void Goomba::behave(){
...
}

c++ "Incomplete type not allowed" error accessing class reference information (Circular dependency with forward declaration)

Had some issues in my code recently surrounding what I now know of as a Circular dependency. In short there are two classes, Player and Ball, which both need to use information from the other. Both at some point in the code will be passed a reference of the other (from another class that will include both .h files).
After reading up on it, I removed the #include.h files from each one and went with forward declaration. This solved the issue of being able to declare the classes in eachother, but I'm now left with an "Incomplete type error" when trying to access a passed reference to the object. There seem to be a few similar examples around, though often mixed with more complex code and hard to narrow down to the basics.
I've rewritten the code in it's simplest form (a skeleton essentially).
Ball.h:
class Player;
class Ball {
public:
Player& PlayerB;
float ballPosX = 800;
private:
};
Player.h:
class Ball;
class Player {
public:
void doSomething(Ball& ball);
private:
};
Player.cpp:
#include "Player.h"
void Player::doSomething(Ball& ball) {
ball.ballPosX += 10; // incomplete type error occurs here.
}
Any help understanding why this is the case would be greatly appreciated :)
If you will place your definitions in this order then the code will be compiled
class Ball;
class Player {
public:
void doSomething(Ball& ball);
private:
};
class Ball {
public:
Player& PlayerB;
float ballPosX = 800;
private:
};
void Player::doSomething(Ball& ball) {
ball.ballPosX += 10; // incomplete type error occurs here.
}
int main()
{
}
The definition of function doSomething requires the complete definition of class Ball because it access its data member.
In your code example module Player.cpp has no access to the definition of class Ball so the compiler issues an error.
Player.cpp require the definition of Ball class. So simply add #include "Ball.h"
Player.cpp:
#include "Player.h"
#include "Ball.h"
void Player::doSomething(Ball& ball) {
ball.ballPosX += 10; // incomplete type error occurs here.
}
Here is what I had and what caused my "incomplete type error":
#include "X.h" // another already declared class
class Big {...} // full declaration of class A
class Small : Big {
Small() {}
Small(X); // line 6
}
//.... all other stuff
What I did in the file "Big.cpp", where I declared the A2's constructor with X as a parameter is..
Big.cpp
Small::Big(X my_x) { // line 9 <--- LOOK at this !
}
I wrote "Small::Big" instead of "Small::Small", what a dumb mistake..
I received the error "incomplete type is now allowed" for the class X all the time (in lines 6 and 9), which made a total confusion..
Anyways, that is where a mistake can happen, and the main reason is that I was tired when I wrote it and I needed 2 hours of exploring and rewriting the code to reveal it.
In my case it was because a typo.
I had something like
struct SomethingStrcut { /* stuff */ };
typedef struct SomethingStruct smth;
Notice how the name of the structure is not the same one as the type definition.
I misspelled struct to strcut.
Look into your code and see wether you have some typos.

Getting "multiple types in one declaration" error in C++

Can anyone tell me why i get a "Block.h:20: error: multiple types in one declaration" error message when compiling this file. Nothing seems to be solving this problem and I'm getting pretty frustrated.
Displayable.h
#include <X11/Xlib.h>
#include <X11/Xutil.h>
// Information to draw on the window.
struct XInfo
{
Display *display;
Window window;
GC gc;
};
// An abstract class representing displayable things.
class Displayable
{
public:
virtual void paint(XInfo &xinfo) = 0;
};
Sprite.h
#include "Displayable.h"
enum Collision {
NO_COLLISION = 0,
TOP_COLLISION,
RIGHT_COLLISION,
BOTTOM_COLLISION,
LEFT_COLLISION
};
class Sprite : public Displayable {
public:
int x, y, width, height;
Sprite();
virtual void paint(XInfo &xinfo) = 0;
Collision didCollide(Sprite *s);
};
Block.h
#include "Sprite.h"
class Block : public Sprite {
public:
virtual void paint(XInfo &xinfo);
Block(int x, int y, int width, int height);
}; <-- **This is line 20**
As is, the code looks OK. I can't see anything wrong with the particular line. However, Xlib is a C library which likes to define quite a number of macros and conventionally uses CamelCase for macros, too. That is, I would suspect that something in your declarations actually happens to be a macro which gets expanded to something the C++ compiler doesn't like. To find this problem I recommend you use the omnipresent -E flag to have a look at the preprocessed source. That is, you'd remove any -o flag (and the name following it) and -c flag but otherwise you'd essentially retain the command line. The result will be written to standard output i.e. you want to redirect the output to more/less or some file.
Alternatively, you can go about and prefix all of your names by a prefix which is unlikely to be used in any of the X11 headers, e.g. parts of some name, offensive words, etc. I tried to reproduce the problem on my system but I didn't get an error message.

Cyclic include trick to hide implementation details in C++ header files

I'm trying to find a clean way to separate implementation details in C++ header files in a big project in order to achieve better information hiding and reduce build time. The problem with C++ is that every time you change a private member declaration, your dependent classes must be rebuilt.
This is a solution I came up with. Is it any good?
The basic Idea is to include a part of the cpp file conditionally in the header. this part contains the implementation declarations and is included only when the implementation file includes the header. in case of the external classes, this details are excluded from header. so client and implementation see two different version of header file. internal declaration changes won't affect clients(no compilation of dependent classes) and headers won't include private details.
Here is the implementation:
HEADER
#pragma once
class Dependency
{
public:
Dependency(void);
~Dependency(void);
void Proc(void);
//PRIVATE Implementaion details stays private
#ifdef Dependency_PRIVATE_IMPELEMENTATION
#define Dependency_PRIVATE_MODE 1
#include "Dependency.cpp"
#undef Dependency_PRIVATE_MODE
#endif
};
CPP
#define Dependency_PRIVATE_IMPELEMENTATION
#include "Dependency.h"
#undef Dependency_PRIVATE_IMPELEMENTATION
#ifdef Dependency_PRIVATE_MODE
private:
int _privateData;
#else
#include <iostream>
Dependency::Dependency(void)
{
//This line causes a runtime exception, see client
Dependency::_privateData = 0;
}
Dependency::~Dependency(void)
{
}
void Dependency::Proc(void)
{
std::cout << "Shiny happy functions.";
}
#endif
CLIENT
#include "stdafx.h"
#include "Dependency.h"
#pragma message("Test.Cpp Compiled")
int _tmain(int argc, _TCHAR* argv[])
{
Dependency d;
d.Proc();
return 0;
//and how I have a run time check error #2, stack around d ?!!
}
It's a pretty interesting question, really. Managing dependencies is important for big projects because the build times ramp up can make even the simplest change daunting... and when it happens people will try to hack it to avoid the rebuild-of-death (tm).
Unfortunately, it does not work.
The Standard explicitly says that classes definitions appearing in different translation units (roughly, files) should obey the One Definition Rule (see ยง 3.2 One definition rule [basic.def.odr]).
Why ?
The problem is a matter of impedance, in a way. The definition of a class contains information on the class ABI (Application Binary Interface), most notably, how such a class is layed out in memory. If you have different layouts of the same class in various translation units, then when putting it altogether, it won't work. It's as if one TU was speaking German and the other Korean. They might be attempting to say the same thing, they just won't understand each other.
So ?
There are several ways to manage dependencies. The main idea is that you should struggle, as much as possible, to provide "light" headers:
include as few things as possible. You can forward declare: types that are shown as arguments or return of functions declaration, types that are passed by reference or pointer but otherwise unused.
hide implementation details
Hum... What does it mean :x ?
Let's pick a simple example, shall we ?
#include "project/a.hpp" // defines class A
#include "project/b.hpp" // defines class B
#include "project/c.hpp" // defines class C
#include "project/d.hpp" // defines class D
#include "project/e.hpp" // defines class E
namespace project {
class MyClass {
public:
explicit MyClass(D const& d): _a(d.a()), _b(d.b()), _c(d.c()) {}
MyClass(A a, B& b, C* c): _a(a), _b(b), _c(c) {}
E e() const;
private:
A _a;
B& _b;
C* _c;
}; // class MyClass
} // namespace project
This header pulls in 5 other headers, but how many are actually necessary ?
a.hpp is necessary, because _a of type A is an attribute of the class
b.hpp is not necessary, we only have a reference to B
c.hpp is not necessary, we only have a pointer to C
d.hpp is necessary, we call methods on D
e.hpp is not necessary, it only appears as a return
OK, let's clean this up!
#include "project/a.hpp" // defines class A
#include "project/d.hpp" // defines class D
namespace project { class B; }
namespace project { class C; }
namespace project { class E; }
namespace project {
class MyClass {
public:
explicit MyClass(D const& d): _a(d.a()), _b(d.b()), _c(d.c()) {}
MyClass(A a, B& b, C* c): _a(a), _b(b), _c(c) {}
E e() const;
private:
A _a;
B& _b;
C* _c;
}; // class MyClass
} // namespace project
Can we do better ?
Well, first we can see that we call methods on D only in the constructor of the class, if we move the definition of D out of the header, and put it in a .cpp file, then we won't need to include d.hpp any longer!
// no need to illustrate right now ;)
But... what of A ?
It is possible to "cheat", by remarking that merely holding a pointer does not requires a full definition. This is known as the Pointer To Implementation idiom (pimpl for short). It trades off run time for lighter dependencies, and adds some complexity to the class. Here is a demo:
#include <memory> // don't really worry about std headers,
// they are pulled in at one time or another anyway
namespace project { class A; }
namespace project { class B; }
namespace project { class C; }
namespace project { class D; }
namespace project { class E; }
namespace project {
class MyClass {
public:
explicit MyClass(D const& d);
MyClass(A a, B& b, C* c);
~MyClass(); // required to be in the source file now
// because for deleting Impl,
// the std::unique_ptr needs its definition
E e() const;
private:
struct Impl;
std::unique_ptr<Impl> _impl;
}; // class MyClass
} // namespace project
And the corresponding source file, since that were the interesting things occur:
#include "project/myClass.hpp" // good practice to have the header included first
// as it asserts the header is free-standing
#include "project/a.hpp"
#include "project/b.hpp"
#include "project/c.hpp"
#include "project/d.hpp"
#include "project/e.hpp"
struct MyClass::Impl {
Impl(A a, B& b, C* c): _a(a), _b(b), _c(c) {}
A _a;
B& _b;
C* _c;
};
MyClass::MyClass(D const& d): _impl(new Impl(d.a(), d.b(), d.c())) {}
MyClass::MyClass(A a, B& b, C* c): _impl(new Impl(a, b, c)) {}
MyClass::~MyClass() {} // nothing to do here, it'll be automatic
E MyClass::e() { /* ... */ }
Okay, so that was the low and gritty. Further reading:
The Law of Demeter: avoid having to call multiple methods in sequences (a.b().c().d()), it means you have leaky abstraction, and forces you the include the whole world to do anything. Instead, you should be calling a.bcd() which hides the details from you.
Separate your code into modules, and provide a clear-well defined interface to each module, normally, you should have far more code within the module than on its surface (ie exposed headers).
There are many ways to encapsulate and hide information, your quest just begins!
This does not work. If you add anything to the class in the private .cpp file, the the users of the class will see a different class than what your implementation thinks it is.
This is not legal, and won't work in many cases. KDE has a great article on what you can and can't change in C++ to preserve ABI compatibility: Binary Compatibility Issues. If you break any of that with your "hidden" implementation, you're going to break the users.
Look at the pimpl idiom for a rather common way of doing what you are trying to achieve.
This won't work. You can easily see it because sizeof(Dependency) for the implementation and the client are different. The client basically sees a different class, accesses different locations in the memory and everything messes up!
Unfortunately, you cannot prevent a rebuild of dependent files if you change a class. However, you can hide the implementation details like this:
Header:
class privateData;
class Dependency
{
private:
privateData *pd;
public:
Dependency(void);
~Dependency(void);
void Proc(void);
};
cpp file
#include <Dependency.h>
class privateData
{
/* your data here */
};
Dependency::Dependency()
{
pd = new privateData;
}
Dependency::~Dependency()
{
if (pd)
delete pd;
}
void Dependency::Proc()
{
/* your code */
}
Note that this is not for you to copy paste. It's just to give you the idea. There may be missing error checking or code that is implied by this usage. One such thing is a copy constructor to prevent shallow copies.
Look at the Opaque_pointer pattern (aka pImpl)
The pattern is typically used for when the Class want to hide the internal implementation but is also have the benefit of that changes to the internal and private structures does not create a recompile since the binary call compatibility is maintained.
The problem with doing it any other way, is that binary compatibility is probably NOT maintained when you changed anything in the class definition, and hence all software will have to be recompiled.
It looks like your solution is a attempt to do exactly this, however you should user a (void*) instead of a int so as to make sure the software compiles correctly on 32 and 64 bit compilers on different platforms -- and just use the cook-book example of Opaque Pointers.