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.