user4702921
user4702921

Reputation:

Hide class implementation from its interface

I have this code for an interface of a class in a header file and its implementation in a separate source file :

First :The Header file "Gradebook.h"

#include <string>

using namespace std;

class Gradebook{
public:
    Gradebook(string);
    void setCoursename(string);
    string getCoursename();
    void displayMessage();
private:
    string nameofCourse;
};

Second :The implementation "Gradebook.cpp"

#include "stdafx.h"
#include "Gradebook.h"
#include <iostream>

using namespace std;

Gradebook::Gradebook(string name){
    setCoursename(name);
}
void Gradebook::setCoursename(string name){
    nameofCourse = name;
}
string Gradebook::getCoursename(){
    return nameofCourse;
}
void Gradebook::displayMessage(){
    cout << "Display message function shows :" << getCoursename() << endl;
}

how can i link these two separate files in order to use only "Gradebook.h" in other project , and hide my implementation from the client-programmer ?

Upvotes: 1

Views: 2130

Answers (1)

uliwitness
uliwitness

Reputation: 8783

There are several answers. It would help to know why you actually want to hide the implementation. Here's the reasons why you might want to do this I can think of offhand.

  1. Protecting trade secrets: Forget it. To be able to execute your code, the computer has to be able to run it. Effectively you can strip away comments, method names and variable names by compiling the code as a static library, even run an obfuscator over it to obscure the control flow (at the cost of slowing it down by adding unneeded jumps), but in the end the code (or the machine code generated from it) has to stay sort of readable or it couldn't be executed.

  2. Make it easier to use your code: If you have several source files and might add more files, and you want your clients to just be able to drop in one file to get all the newest changes without having to add individual source files, compile it as a static or dynamic library. Then you can hand someone the library plus the headers and they can just use them.

    You can also create an "umbrella header" that includes all the other headers. That way, clients can simply add the path to your library's includes folder to their compiler invocation/project file and include the one header, which includes all others. If you add or split up a header, you just change the umbrella to include the new headers and all projects that use it keep working.

    Note that using a library will limit your clients: They can't step through your code in the debugger easily, they can't fix and compile stuff easily. If they need your code to run on a new platform, or want to use different optimization settings in the compiler, they can't just recompile it.

    On the other hand if you plan to sell your library, you might want to hold on to your sources. Customers who don't care about the security of having the code if you ever go out of business can get a cheaper version of the library without the source code, you can charge them extra if they want any of the other features by making them buy a version for the new platforms that you coded for them, etc.

  3. Prevent clients from accidentally relying on implementation details: You don't really need to do anything for this except split up your code into public and private files. Usually your implementation file is private and your headers are public, but you may have some private headers for internal classes.

    Since C++ does not allow defining instance variables or methods that aren't declared in the header's class declaration like other languages do that support categories or class extensions, you may have to resort to the Private Implementation (aka 'pimpl') pattern.

    What this usually means is that you declare one class that defines the public API that simply wraps a pointer to the actual class that contains the real implementation and calls through to it. It usually only has one instance variable, pimpl, which is the pointer to the other class. You simply forward-declare the private class using class Foo; and thus your clients' code doesn't know anything about the private class (unless they explicitly peek into the implementation file or private header, e.g. when fixing a bug).

  4. Create a single-file class I mention this last because it is generally a stupid thing to do, but just in theory, you could also move the implementation file's content into the header. Then clients only need to include the header and get all the sources. This has lots of downsides, though, like making code harder to read, slowing down compile times, and requiring the client to deal with duplicate definitions of the class caused by including the file from several .cpp files. In short: Don't do it.

Upvotes: 2

Related Questions