Reputation: 2063
(In C++) I have a class whose structure is declared in a header file. That header file is included in lots of source files, such that when I edit it I need to recompile lots of files.
The class has a set of private functions which are only called in one source file. Currently they are declared in the class structure in the header file. When I add a new function of this type, or edit the arguments, it therefore causes recompilation of lots of files. I would like to declare the functions somewhere else, such that only the file that defines and calls them is recompiled (to save time). They still need to be able to access the internal class variables, though.
How can I achieve this?
Upvotes: 23
Views: 23626
Reputation: 1
Here is a clean solution (no dynamic allocation or pointer redirect). keep variables and public functions in SomeClass, and write the implementations in SomeClass_Impl. those Impl functions can be moved to source file too (incase you like a totally clean header file).
.h
#pragma once
//forward declare the private
struct SomeClass_Impl;
//public struct with public functions
struct SomeClass
{
float Values[4] = {};
SomeClass_Impl* Impl() { return (SomeClass_Impl*)this; }
const SomeClass_Impl* Impl() const { return (const SomeClass_Impl*)this; }
void Print() const;
};
.cpp
#include "SomeClass.h"
#include <iostream>
//private implementation, should only contains functions
struct SomeClass_Impl : SomeClass
{
float GetSum() const
{
float Sum = 0;
for(float V : Values)
Sum += V;
return Sum;
}
float GetMinValue() const
{
float MinVal = Values[0];
for (int i = 1; i < 4; i++)
MinVal = std::min(MinVal, Values[i]);
return MinVal;
}
};
static_assert(sizeof(SomeClass) == sizeof(SomeClass_Impl), "_Impl should not have any member variables.");
void SomeClass::Print() const
{
//'this' can be casted to SomeClass_Impl without any cost
std::cout << "Sum:" << Impl()->GetSum() << " MinValue:" << Impl()->GetMinValue() << '\n';
}
Usage:
SomeClass A;
A.Values[0] = 1;
A.Values[1] = 2;
A.Values[2] = 3;
A.Values[3] = 4;
A.Print();
Upvotes: 0
Reputation: 21773
Create an abstract base class which contains only the public functions and reference this in your headers. Create your real class as an implementation somewhere else. Only source files which need to create your class need to see the implementation class header.
Upvotes: 1
Reputation: 2063
There is no way to declare member functions of a class outside the main class declaration. So, if you want to declare, outside of the class in question, functions that can access member variables of a particular instance of the class, then I see no alternative but to pass that instance to the function. Furthermore, if you want the functions to be able to access the private and protected variables you will need to put them in a new class and make the original class a friend of that. E.g.
header.h:
class FooImpl;
class Foo {
public:
int bar();
friend class FooImpl;
private:
int var;
}
impl.cpp:
#include "header.h"
class FooImpl {
public:
int bar(Foo &);
}
int FooImpl::bar(Foo &foo) {
return foo.var;
}
int Foo::bar() {
return FooImpl::bar(*this);
}
Upvotes: 6
Reputation: 91270
Use the pImpl idiom - Your visible class keeps a pointer to the real class and forwards calls to public member functions.
EDIT: In response to comments
// Foo.h:
class FooImpl; // Do *not* include FooImpl.h
class Foo {
public:
Foo();
~Foo();
//.. also need copy ctor and op=
int bar();
private:
FooImpl * Impl;
};
// FooImpl.h:
class FooImpl {
public:
int bar() { return Bar; }
private:
int Bar;
};
// Foo.cpp:
#include "FooImpl.h"
Foo::Foo() { Impl = new FooImpl(); }
Foo::~Foo() { delete Impl; }
int Foo::bar() { return Impl->bar(); }
Keep the actual implementation of your class in FooImpl
- Foo
should have copies of the public members of FooImpl
and simply forward calls to these. All users will include only "Foo.h" - you can change all the private details of FooImpl
without the users of Foo
seeing any changes.
Upvotes: 14