C++ Interface Implementation and Subclassed Object Instatiation - c++

Update
The actual context is that I need to create a package to submit to NIST, trying to test a Facial Recognition Algorithm I am working on. The API to use can be found at NIST API and the project to git is at git project
Some code to make a summary of the scenario:
a.h - interface A, composed by pure virtual methods and one static method (frvt11.h at NIST project)
class A {
public:
virtual ~A() {}
virtual void pure_virtual_method_a() = 0;
virtual void pure_virtual_method_b() = 0;
static int static_method();
}
b.h - header file for b.cpp, where interface A's methods are implemented
#include "a.h"
class B : A {
public:
void pure_virtual_method_a();
void pure_virtual_method_b();
static int static_method();
}
b.cpp - Implementation of interface A's methods.
#include "b.h"
void pure_virtual_method_a() {/*implementation*/};
void pure_virtual_method_b() {/*implementation*/};
int static_method() {/*implementation*/};
c.cpp - A file with only a main method and where I want to instantiate an object of B to use its methods.
#include "b.h"
int main(){
B obj;
obj.pure_virtual_method_a();
return 0;
}
Question 1: To instantiate an object of B in c.cpp, do I need to write the header file b.h like above? That seems to be so redundant! It looks like interface A is so unnecessary :-(
Question 2: Is the code presented the right way to implement interface A, and use an object of type B?
Question 3: Do I need to declare a constructor for B in b.h and implement it in b.cpp?

Question 1
You miss a semicolon after the closing curly brace, and it is better to specify that the pure virtual methods you implement in B are marked as override. This allows the compiler to emit warnings in case you forget to change any of the overridden method declarations as soon as the corresponding pure virtual methods in A would change. Thus you will end up with:
#include "a.h"
struct B : public A {
void pure_virtual_method_a() override;
void pure_virtual_method_b() override;
static int static_method();
};
From this it is also clear that for the compiler to be able to declare B as a type, A needs to be declared as well. For example, how would the compiler check the override keyword if it did not yet already have a declaration of A. In case you would not have any overridden virtual methods, A still needs to be known, since the compiler needs to be able to deduce the size of B.
Furthermore, as mentioned in the comments, declaring B as a struct allows you to drop the public keyword, since the default visibility of a struct is public in contrast with private default visibility for a class. This is the only difference between classes and structs in C++. Thus, for interfaces, using structs is more natural.
Question 2
Not completely. b.cpp should look something along the following lines:
#include "b.h"
void B::pure_virtual_method_a() {/*implementation*/};
void B::pure_virtual_method_b() {/*implementation*/};
int B::static_method() {/*implementation*/};
Otherwise, you declare and define three methods in the global namespace, and the linker will complain about undefined references to the three methods of B declared in b.h.
Furthermore, B needs to know how to derive from A, either publicly, protected, or private.
Furthermore, it is a good idea to add include guards to the header files, to prevent the compiler from seeing the same type declaration twice when compiling an object file like a.o or b.o:
#ifndef B_H
#define B_H
#include "a.h"
struct B : public A {
...
};
#endif
Finally, static_method() needs an implementation for A as well, static methods can not be virtual.
Question 3
You do not need to implement a constructor for B necessarily. In case you do not define one, the compiler will generate a default constructor for B. However, in case you define a non-default constructor for A, you will need to define one for B in case you want to construct instances of type B. The constructor can be implemented inline in the header file, or can be defined in b.cpp.

Question 1.
You can use Factory Pattern, then u can add b.h only in Factoru files? and return pointers or smart pointer to A class. For eample, it can be factory function like:
std::unique_ptr<A> getObject(/*params*/)
{
return std::make_unique<B>(/*params*/)
}
And then in c.cpp file:
auto obj = getObject(/*params*/);
obj->pure_virtual_method_a();
Then you can create another implementations of A interface, and return them from factory.
Question 2.
should be class B : public A
and
void B::pure_virtual_method_a() {/*implementation*/};
void B::pure_virtual_method_b() {/*implementation*/};
int B::static_method() {/*implementation*/};
Question 3.
If you need constructor in class A or constructor exactly for class B, you need to define and implement B class constuctor.

Related

How to Foward Declare Classes Across Files C++

I have been trying to figure out how to forward declare classes across multiple files in C++. I was able to successfully do it with two classes, but doing this across many classes puzzled me. I tried forward declaring all the classes in a header file and including that in all the classes, but I got the error of incomplete classes. I looked into it, but all the solutions seemed unreasonable or confused me. Can you please explain a good way to do it.
If it helps here is some example code of the issue that specifically occurring. Class A is included in Class C, but Class A also includes Class B which holds Class C resulting in an error because Class C has not been declared.
Class Forward Declaration
//Tried "Class Name {};" but that also failed
Class A;
Class B;
Class C;
Class A
//Class A
#include "B.h"
class A{
private:
B b;
public:
void SetBInt(int set) {b.SetInt(set);}
}
Class B
//Class B
#include "C.h"
class B{
private:
C c;
int i = 0;
public:
void SetInt(int set){i = set;}
}
Class C
//Class C
#include "A.h"
class C{
private:
int i = 0;
public:
void SetInt(int set){i = set;}
}
You have to avoid circular dependencies. One common way to avoid them is by pre-declaring the type, and not having any instances or function calls of that type in the header.
You do this by changing instances, such as B b, into references or pointers: B* b. You also have to move any code that uses b into the CPP file, so you can #include "B.h" prior to using it.
For example, instead of
// we'll remove this header's dependency on B shortly
#include "B.h"
class A
{
B b;
public:
A() { b.SetInt(0); }
};
You do something like this:
class B;
class A
{
B *b; // *pointers and &references to a predeclared class are fine.
public:
A();
~A();
};
... and then in A.cpp:
#include "A.h" // ALWAYS include your own header first
#include "B.h"
A::A()
{
// we didn't need to know how big B was until now, when we're about to make one and
// run its constructor. We'll also need to know what functions are available, and the
// types of all its parameters (or lack of parameters).
b = new B();
b->SetInt(0);
}
A::~A()
{
delete b; // for every "new" there must be a "delete"
}
Yes, this would be (much) better with std::unique_ptr<B> b instead of a raw pointer. With a smart pointer we wouldn't need an explicit destructor. I just didn't want to throw too much potentially new stuff at someone still learning.
Alternatively, you could pass a reference into the constructor, and use the member initializer list (you can only set references when they're constructed). This raises problems with "Object Lifetime". If the instance of B you pass in at construction time is destructed before A is done with it, you're program will violently crash (if you're lucky: that way you'll have a good idea of what the problem is) the next time it's used. Best to avoid it till you have considerably more experience under your belt.

same #include statements in derived classes

I have two questions
lets say there is a base class and several derived classes, the derived classes are going to have all of the #include statements (like #include <iostream> etc) and using lines of the base class.
1. is it considered a good practice to write the base class's #include statements and using lines in the in the derived classes h. file anyway?
2.same question regarding composition - class A has an object of class B as a member, is it a good practice to writes Bs#include` statements in A's h. file anyway?
thanks!
I think it is a good practice to have each include file actually #include any of the definitions it needs, so that in your main program, you can #include your most deeply derived class without having to have additional #include statements for the definitions that class needs.
You can have class definitions contain pointers to previously undefined classes, as follows:
class forward_ref;
class myClass :
Public:
myClass(){}
forward_ref* ptr_to_forward_ref;
};
lets say there is a base class and several derived classes, the
derived classes are going to have all of the #include statements (like
#include <iostream> etc) and using lines of the base class.
Not at all.
First of all, you are not supposed to put using lines at top-level scope in header files. This is a common beginners' mistake.
Second, what makes you think the derived class needs all #includes of the base class? The derived-class header file needs to include the base-class header file, and the derived-class implementation file needs to include the derived-class header file.
This already gives you all includes.
base.h:
#include <string>
class Base
{
// ...
virtual std::string f(); // no `using`
};
derived.h:
#include "base.h"
// no need for <string> here
class Derived : public Base
{
// ...
virtual std::string f();
};
derived.cpp:
#include "derived.h"
// no need for <string> here
std::string Derived::f() // could have used `using std::string`
{
// ...
}
Now of course, it's technically possible to actually do it otherwise, in a more complicated fashion, like this:
base.h:
// no <string>?!
class Base
{
// ...
virtual std::string f();
};
derived.h:
#include "base.h" // still no <string>?!
class Derived : public Base
{
// ...
virtual std::string f();
};
derived.cpp:
#include <string> // ah, OK
#include "derived.h"
std::string Derived::f()
{
// ...
}
This works only because the compiler doesn't separately compile header files but only compilation units (~= .cpp files) as a whole, after all includes have been processed.
But talk about horrible programming style. Why would you want to force everyone who derives from your class to include extra headers?
2.same question regarding composition - class A has an object of class B as a member, is it a good practice to writes Bs#include` statements
in A's h. file anyway?
It depends. If A's header needs access to any of B's members, then you have to use an include, and in that case, again, you just include what you need in b.h and let a.h #include "b.h".
If A's header only needs a pointer or a reference to B, or just a return value, then you can use a forward declaration in order to potentially speed up compilation. Of course, speeding up compilation is not something a C++ beginner should care about, because a lot of time will pass until you will be developing software which take hours to build :)
Anyway, for completeness' sake:
a.h:
class B; // forward declaration, no #include
class A
{
// ...
B f();
B *ptr;
B &ref;
};
a.cpp:
#include "a.h"
#include "b.h" // need the include here
B A::f()
{
B obj;
return obj;
}
b.h:
class B
{
// ...
};
In answer to question 2: typically you would include class B's header file in A's header file (so all the includes needed for A will automatically be included).
However, as pointed out in Logicrat's answer, you could alternatively include only a pointer to B in A. In this case you can use a forward declaration of B in A.h instead of including B.h. The downside to this is that all functions that need to make use of B must then go in A.cc (which will definitely have to include B.h). The advantage is that you can greatly reduce the quantity of code in the header files (since each #include copies an entire header file into the current file just before compilation), which can speed up compilation times.

Masking as much as possible of class implementation in C++

I have two classes A and B where B uses objects of class A, something like this
class A {
private:
int foo_;
A(const int &foo): foo_(foo) {}
}
class B {
// STUFF
inline C operator()(A a)
}
For the moment, I have put the definition of both in a .h file and the code compiles and executes correctly.
My question is: how much can I mask of the implementation of class A, for example by moving code lines to a .cpp file to be separately compiled and linked? Can I mask the implementation of private members and methods (everything which is not directly accessed by an external user)? How? Which C++ keywords should I use?
Thank you very much in advance.
Masking implementations can be done by PIMPL idiom or using simple polymorphism, which is a Factory method pattern. Basically, you create an interface class, say IA like so:
/* File: A.h */
#include <memory> /* For std::shared_ptr */
class IA;
/* Change the line below to boost::shared_ptr<> or
* another implementation of a shared-pointer.
* Read more:
* http://en.wikipedia.org/wiki/Smart_pointer#shared_ptr_and_weak_ptr
*/
typedef std::shared_ptr<IA> APtr;
class IA {
public:
static APtr Create(const int foo);
IA(){}
virtual ~IA(){}
virtual void somePublicMethod() = 0;
};
In your A.cpp you'll have it's implementation:
/* File: A.cpp */
#include "A.h"
class A : public IA
{
public:
A(const int foo):foo_(foo){}
void somePublicMethod(){/* Your awesome implementation goes here */}
};
APtr IA::Create(const int foo)
{
return APtr(new A(foo));
}
This way, you pass around only the interface and expose only the public methods to outside world, which the internals are in your CPP files.
Advantages:
Hide implementation completely from users
Disadvantages:
You'll need to create an interface for every class you intend to hide
Your users will have to call the factory method to create an instance. For e.g. Create() in the above example.
You will always have your class instances to be in heap memory than in stack, i.e., your implementation instances will always have to be a pointer. (Read More: Heap vs. Stack Memory)
If you don't need C operator()(A a) to be inline you could forward declare the parameter A as follows
class A;
Then you can move its definition to another header and include it in the places it's used.
Here are more details about forward declaration.
Regarding what the pImpl idiom can hide:
you can move all function definitions (the implementation thereof, including constructors and their initialisation lists) into the Impl class
which then lets you put private types, data members functions into the Impl class EXCEPT where they affect class behaviour (e.g. private constructors, destructors and operators have implications for the user of the class)
you can move definitions and initialisation of class static data members into the implementation file
as per Arne's comment, private base classes can typically be moved into the implementation (unless you're using typedefs etc. from them in the public or protected data members, and that's ugly as per his comment!)

Does a pure abstract C++ class declared in a header used in different projects (without compile time linking) share the same Virtual Table model?

I have a C++ header declaring a class composed of pure virtual methods only. I have two DLLs using that header, (with one implementing that interface) but not linked at compile time. One DLL is loading the other one dynamically, passing a pointer of the implemented interface to the other. Are these DLL's sharing the same virtual table structure?
Of course, the class header is enough to build the complete class (speaking about the in-memory layout here, how everything is positioned, not the actual data inside it), including the precise virtual table structure.
Think about it, each linking object (your .cpp files) are compiled separately, with only the header files in common, but at compile time the compiler has to know the precise structure of the virtual table to route virtual calls correctly.
Doozy of a question to read through by the way...
If I understand correctly, you've got something like this:
A.h
class A
{
public:
virtual void foo()=0;
}
B.cpp
#include <A.h>
class B : public A
{
public:
void foo()
{}
}
C.cpp
#include <A.h>
void bar(A * a)
{}
So B.cpp has a class implementing A, and C.cpp has some function accepting a pointer to an instance of A (which you provide with an instance of B). Is that correct?
If so, then yes, these share a vtable. The vtable is created by compiling class B, and C.cpp doesn't have any vtables of its own at all.
You're safe.
The order in which the methods appear in the vftable is determined by the base class structure, and that's all you should care about. But this is compiler specific, so use the same compiler for generating the dll's. Don't rely on them being backward-compatible (or at least check the documentation).
Assume you have the following header:
//header.h
class A
{
public:
virtual void foo() = 0;
virtual void goo() = 0;
};
And you have B.dll with the following class:
class B : public A
{
public:
virtual void foo() {}
virtual void goo() {}
}
Now, in X.dll, you receive a pointer to an A that is a B object created in B.dll.
The call
void test( A* a )
{
a->foo();
}
will invoke B::foo().
One neat experiment you can try is to compile B.dll with header.h and when you compile X.dll, invert the order of the methods in header.h:
//header.h
class A
{
public:
virtual void goo() = 0;
virtual void foo() = 0;
};
In this case, although you should never do this, the same call to test() in X.dll will probably call the method B::goo(). That is because X.dll assumes the vftable present in the header. It's undefined behavior though; I just wrote this example to make a point.
This is all compiler dependent, but in general, when a class is pure virtual and none of the member functions is defined in a translation unit, the compiler will generate the vtable as a weak symbol. In your particular case, the different translation units will generate separate exactly equal vtables for the base type and the linker/loader will discard all but one of the symbols as it would with any other weak symbol (think of a templated non-inlined function).
Note however that the generation of the vtable is not standardized which means that if you mix code from two different compilers or even versions you can cause an ODR violation.

Forward declaration of class doesn't seem to work in C++

The follwing code is compiled in VC++6. I don't understand why I am getting the compilation error C2079: 'b' uses undefined class 'B' for the following code.
Class B Source
#include "B.h"
void B::SomeFunction()
{
}
Class B Header
#include "A.h"
struct A;
class B
{
public:
A a;
void SomeFunction();
};
struct A Header
#include "B.h"
class B;
struct A
{
B b;
};
If I changed class B header to the following, then there will be no error. But the header declaration won't be at the top!
Class B Header with weird header declaration
struct A;
class B
{
public:
A a;
void SomeFunction();
};
#include "A.h"
In order to define a class or struct, the compiler has to know how big each member variable of the class is. A forward declaration does not do this. I've only ever seen it used for pointers and (less often) references.
Beyond that, what you're trying to do here cannot be done. You cannot have a class A that contains an object of another class B that contains an object of class A. You can, however, have class A contain a pointer to class B that contains an object of class A.
B.cpp
#include "B.h"
void B::SomeFunction()
{
}
B.h
#ifndef __B_h__ // idempotence - keep header from being included multiple times
#define __B_h__
#include "A.h"
class B
{
public:
A a;
void SomeFunction();
};
#endif // __B_h__
A.h
#ifndef __A_h__ // idempotence - keep header from being included multiple times
#define __A_h__
#include "B.h"
class B; // forward declaration
struct A
{
B *b; // use a pointer here, not an object
};
#endif // __A_h__
Two points. First, be sure to use some form of idempotence to keep the headers from being included multiple times per compilation unit. Second, understand that in C++, the only difference between classes and structs is the default visibility level - classes use private visibility by default while structs use public visibility by default. The following definitions are functionally equivalent in C++.
class MyClass
{
public: // classes use private visibility by default
int i;
MyClass() : i(13) { }
};
struct MyStruct
{
int i;
MyStruct() : i(13) { }
};
Forward declarations, like
struct A;
or
class A;
Introduce A as an incomplete type and it remains incomplete until end of type's definition is reached. There are things you can do with incomplete types and things you can't. You can
Declare variables (or members) of type "pointer to A" and "reference to A"
Declare functions which take arguments of type A or return type A
You can't
Declare variables (nor members) of type A
Dereference pointers to A or access any members of references to A
Define subclasses of A.
In your code you try to declare struct member of incomplete type. It's illegal. Only pointers and references are allowed.
public:
A a;
You are trying to create the object of A with only forward declaration. Compiler at this moment ( with only forward decl) cannot decide the size of the object A and hence, it cannot allocate memory required for A. So you cannot create objects with only forward decl.
Instead replace with:
A* a;
Pointer or reference to A without A's class definition will work fine.
Two issues jump out at me here.
1: You've written Struct A instead of struct A; note the lower-case "s". Your compiler might consider the equivalent, but I don't think it's standard C++.
You have defined a circular reference between A and B. Each A object must contain a B object, but each B object must contain an A object! This is a contradiction, and will never work the way you want it to. The usual C++ way to solve that problem is to use pointers or references for A::b or B::a (or both).
You alse include A.h from B.h and B.h from A.h. You should at least use preprocessor macros:
#ifndef __A_H__
#define __A_H__
// A.h contents
#endif
so that file won't be included more than once.
If you create an instance of A, that will create an instance of B (member var) which will create an instance of A (member var) which will create an instance of B which will create an instance of A and so on...
The compiler should not allow this since it requires infinite memory.
To solve this, either A or B must use a reference/pointer to the other class.