C++ program behaviour depending on source code file set - c++

I want to create a program which behaves differently depending on a facultative additional source code file to compilation (where some people might add some differing functionality). I thought about function overloading, similar to the (non-compilable) following code:
file1.cpp:
#include <iostream>
#include <string.h>
using namespace std;
class base {
public:
void ausgeb() { cout<<"here output base"<<endl; }
};
class derive: public base;
int main(int argc, char** argv)
{
derive beisp;
beisp.ausgeb();
}
file2.cpp:
#include <iostream>
#include <string.h>
using namespace std;
class base;
class derive : public base
{
public:
void ausgeb() { cout<<"here output derive"<<endl; }
};
Now I wished that:
g++ -o o1 file1.cpp file2.cpp
and
g++ -o o2 file1.cpp
should produce executable files with differing output.
Might there be a possibilty to meet that need?

This solution is gcc specific, if you switch compiler, it most probably won't work any more...
file1.cpp:
#include <iostream>
void printOut() __attribute__((weak));
void printOut()
{
::std::cout << "weak" << ::std::endl;
}
int main(int, char*[])
{
printOut();
return 0;
}
file2.cpp:
#include <iostream>
void printOut()
{
::std::cout << "strong" << ::std::endl;
}
More advanced (left out printOut implementations):
file1.h:
class Base
{
virtual void printOut();
}
file1.cpp
#include "file1.h"
Base& getInstance() __attribute__((weak));
Base& getInstance()
{
static Base theInstance;
return theInstance;
}
int main(int, char*[])
{
Base& instance = getInstance();
instance.printOut();
}
file2.cpp:
#include "file1.h"
class Derived : public Base
{
virtual void printOut();
}
Base& getInstance()
{
static Derived theInstance;
return theInstance;
}
More general solution, via defining a preprocessor symbol:
file1.h:
class Base
{
virtual void printOut();
}
file1.cpp
#include "file1.h"
#ifdef USE_DERIVED
#include "file2.h"
#endif
void Base::printOut()
{
}
int main(int, char*[])
{
#ifdef USE_DERIVED
Derived instance;
#else
Base instance;
#endif
instance.printOut();
}
file2.h:
#include "file1.h"
class Derived : public Base
{
virtual void printOut();
}
file2.cpp:
void Derived::printOut()
{
}
and compile with g++ file1.cpp in one case and g++ -DUSE_DERIVED file1.cpp file2.cpp in the other one.

Related

How do you forward declare classes that exist within a namespace? [duplicate]

I am trying to use forward declarations in header files to reduce the number of #include used and hence reduce dependencies when users include my header file.
However, I am unable to forward declare where namespaces are used. See example below.
File a.hpp:
#ifndef __A_HPP__
#define __A_HPP__
namespace ns1 {
class a {
public:
a(const char* const msg);
void talk() const;
private:
const char* const msg_;
};
}
#endif //__A_HPP__
File a.cpp:
#include <iostream>
#include "a.hpp"
using namespace ns1;
a::a(const char* const msg) : msg_(msg) {}
void a::talk() const {
std::cout << msg_ << std::endl;
}
File consumer.hpp:
#ifndef __CONSUMER_HPP__
#define __CONSUMER_HPP__
// How can I forward declare a class which uses a namespace
//doing this below results in error C2653: 'ns1' : is not a class or namespace name
// Works with no namespace or if I use using namespace ns1 in header file
// but I am trying to reduce any dependencies in this header file
class ns1::a;
class consumer
{
public:
consumer(const char* const text) : a_(text) {}
void chat() const;
private:
a& a_;
};
#endif // __CONSUMER_HPP__
Implementation file consumer.cpp:
#include "consumer.hpp"
#include "a.hpp"
consumer::consumer(const char* const text) : a_(text) {}
void consumer::chat() const {
a_.talk();
}
Test file main.cpp:
#include "consumer.hpp"
int main() {
consumer c("My message");
c.chat();
return 0;
}
UPDATE:
Here is my very contrived working code using the answer below.
File a.hpp:
#ifndef A_HPP__
#define A_HPP__
#include <string>
namespace ns1 {
class a {
public:
void set_message(const std::string& msg);
void talk() const;
private:
std::string msg_;
};
} //namespace
#endif //A_HPP__
File a.cpp:
#include <iostream>
#include "a.hpp"
void ns1::a::set_message(const std::string& msg) {
msg_ = msg;
}
void ns1::a::talk() const {
std::cout << msg_ << std::endl;
}
File consumer.hpp:
#ifndef CONSUMER_HPP__
#define CONSUMER_HPP__
namespace ns1
{
class a;
}
class consumer
{
public:
consumer(const char* text);
~consumer();
void chat() const;
private:
ns1::a* a_;
};
#endif // CONSUMER_HPP__
File consumer.cpp:
#include "a.hpp"
#include "consumer.hpp"
consumer::consumer(const char* text) {
a_ = new ns1::a;
a_->set_message(text);
}
consumer::~consumer() {
delete a_;
}
void consumer::chat() const {
a_->talk();
}
File main.cpp:
#include "consumer.hpp"
int main() {
consumer c("My message");
c.chat();
return 0;
}
To forward declare class type a in a namespace ns1:
namespace ns1
{
class a;
}
To forward declare a type in multiple level of namespaces:
namespace ns1
{
namespace ns2
{
//....
namespace nsN
{
class a;
}
//....
}
}
Your are using a a member of consumer which means it needs concrete type, your forward declaration won't work for this case.
For nested namespaces, since C++17, you can do
namespace ns1::ns2::nsN
{
class a;
}
Apart to forward-declare the class from within its namespace (as #billz says), remember to either use (prepend) that namespace when referring to the forward-declared class, or add a using clause:
// B.h
namespace Y { class A; } // full declaration of
// class A elsewhere
namespace X {
using Y::A; // <------------- [!]
class B {
A* a; // Y::A
};
}
Ref: Namespaces and Forward Class Declarations

Storing pointers to static variables

I've created a unit test framework for c++ which I want to port to C later and I've come across a problem where a unit test simply won't run. Unit tests are created in .cpp files and only one .cpp file should run all the tests.
To simplify a bit, this is how a test is typically created:
main.cpp
#define UNIT_TEST_IMPL // or whatever
#include "unit_test.hpp"
int main()
{
for(const auto& test : tests_queue)
test->run();
return 0;
}
unit_test.hpp
#pragma once
struct Base
{
protected:
Base() = delete;
Base(Base* ptr);
public:
virtual void run() = 0;
};
#if defined(UNIT_TEST_IMPL)
#include <vector>
std::vector<Base*> tests_queue;
Base::Base(Base* ptr)
{
tests_queue.push_back(ptr);
}
#endif
test.cpp
#include "unit_test.hpp"
#include <iostream>
struct Test : Base
{
Test()
: Base(this)
{}
void run() override
{
std::cout << "new test" << std::endl;
}
};
struct Test2 : Base
{
Test2()
: Base(this)
{}
void run() override
{
std::cout << "new test2" << std::endl;
}
};
static Test test;
static Test2 test2;
The question is: why is it not running the tests defined in test.cpp (if I create tests in the main.cpp file they run perfectly fine)? My guess is that the problem lies in the way I am storing Base pointers but I don't know.
The compiler is g++ 6.4.0
static-initialization-order-fiasco in action:
Initialization order of global across translation units is unspecified, so if test, test2 are instantiated before tests_queue, the later initialization would destroy the registration.
One possible correction:
#pragma once
struct Base
{
protected:
Base();
public:
virtual ~Base() = default;
virtual void run() = 0;
};
#if defined(UNIT_TEST_IMPL) // Should be defined only once.
#include <vector>
std::vector<Base*>& get_tests_queue()
{
static std::vector<Base*> tests_queue;
return tests_queue;
}
Base::Base()
{
get_tests_queue().push_back(this);
}
#endif
so your main.cpp would be:
#define UNIT_TEST_IMPL // or whatever
#include "unit_test.hpp"
int main()
{
for(const auto& test : get_tests_queue())
test->run();
}
Your unitTests would be unmodified:
#include "unit_test.hpp"
#include <iostream>
struct Test : Base
{
void run() override { std::cout << "new test" << std::endl; }
};
struct Test2 : Base
{
void run() override { std::cout << "new test2" << std::endl; }
};
static Test test;
static Test2 test2;
Demo
My bets go to some form of Static Initialization Fiasco
Not sure about it, but you cannot count on global variables (your Test1 and Test2 variables defined in test.cpp being initalized befor Main runs.
As a rule of thumb avoid global variables if you can (and in this case, you probably can).
But mainly, your program should not make any assumption on initialization order of global/static variables. Here you are assuming the two globals are initialized before main. Possibly, they are not

c++, Base class constructor seperate declearation and implementation

In my C++ program I have separate .h and .cpp files and everything is working so far except when I want to use a base class constructor for a derived class. It is working but only if I put the function definition if the class deceleration.
Here's the working code for the .h file.
#include <iostream>
using namespace std;
class property
{
public:
property();
property(const property & src);
property(int src);
~property();
virtual int disp() const = 0;
int get_ownable();
private:
protected:
int ownable;
};
class rr : public property
{
public:
rr();
rr(const rr & src);
rr(int src):property(src)
{cout << "\nderived class was called\n";};
~rr();
virtual int disp() const;
private:
protected:
};
The imp.cpp (implementation) file is
#include "head.h"
#include <iostream>
using namespace std;
//property class implimentations
property::property()
{
ownable = 0;
}
property::property(const property & src)
{
ownable = src.ownable;
}
property::property(int src)
{
ownable = src;
cout << "\nparent class called\n";
}
property::~property()
{
}
int property::get_ownable()
{
return ownable;
}
rr::rr()
{}
rr::rr(const rr & src)
{
ownable = src.ownable;
}
/*
rr::rr(int src):property(src)
{
cout << "\nderived class was called\n";
}
*/
rr::~rr()
{
}
int rr::disp() const
{
}
There is other code but it is working fine and not connected to this. The output is
parent class called
derived class was called
So that works just fine but if I un-comment out the function in the .imp file and remove the declaration in the .h
rr(int src):property(src);
I get the error
head.h: IN constructor 'rr::rr(int)':
head.h 113: error: expeted '{' at end of input
imp.cpp: at global scope:
imp.cpp:348:error: redefiniton of 'rr::rr(int);
head.h.113: error: 'rr::rr(int); previousle defined here
All the examples I can find on line of how to do this do it with all the functions defined in the class declaration. I can't find any examples of how to do it with 2 files. Can anyone tell me how to define the base class constructor call in a separate file?
I am on a Linux system using g++ compiler.
Like this
BaseClass.h
#pragma once
class BaseClass {
public:
BaseClass(int a);
private:
int a_private;
};
BaseClass.cpp
#include "BaseClass.h"
#include <iostream>
using std::cout;
using std::endl;
BaseClass::BaseClass(int a) {
cout << "Base class constructor called" << endl;
this->a_private = a;
}
Derived.h
#pragma once
#include "BaseClass.h"
class Derived : public BaseClass {
public:
Derived(int a);
private:
int a_private;
};
Derived.cpp
#include "Derived.h"
#include <iostream>
using std::cout;
using std::endl;
Derived::Derived(int a) : BaseClass(a) {
cout << "Derived class constructor called" << endl;
this->a_private = a;
}
main.cpp
#include "BaseClass.h"
#include "Derived.h"
int main() {
Derived d(2);
return 0;
}
Compiling with the command
g++ main.cpp Derived.cpp BaseClass.cpp and running will result in the following output
Base class constructor called
Derived class constructor called
As mentioned in the comments (credits #IgorTandetnik), initializer lists should be used only in the implementation file. Not in the header file (provided the class is not templated).

Multiple classes with the same name causing vtable problems

I have an interesting problem that crept up and I was wondering why GCC/G++ doesn't catch this and throw some kind of error.
Apologies for how many files this takes, but I've reduced the problem as much as possible.
Interface.H
class BaseClass {
public:
virtual void hello() = 0;
};
void rememberClass(BaseClass* foo);
void callFunc();
Interface.C
#include "Interface.H"
namespace {
typedef void (BaseClass::*memfunptr)();
memfunptr func;
BaseClass* obj;
}
void rememberClass(BaseClass* foo) {
func = &BaseClass::hello;
obj = foo;
}
void callFunc() {
(obj->*func)();
}
Class1.H
class Class1 {
public:
Class1();
};
Class2.H
class Class2 {
public:
Class2();
};
Class1.C
#include "Interface.H"
#include "Class1.H"
#include <iostream>
class HelloClass : public BaseClass {
public:
HelloClass() {}
void hello() {
std::cout << "Calling Hello" << std::endl;
}
};
Class1::Class1() {
HelloClass* foo = new HelloClass();
rememberClass(foo);
}
Class2.C
#include "Interface.H"
#include "Class2.H"
#include <iostream>
class HelloClass : public BaseClass {
public:
HelloClass() {}
void hello() {
std::cout << "Calling Hello 2" << std::endl;
}
};
Class2::Class2() {
HelloClass* foo = new HelloClass();
rememberClass(foo);
}
main.C
#include "Class2.H"
#include "Interface.H"
int main(int argc, char** argv) {
Class2 a;
callFunc();
}
Output
g++ Class1.C Interface.C main.C Class2.C
./a.out
Calling Hello
As you can see above, Even though I am constructing a Class2, it prints the output from Class1. This is because the vtable for HelloClass in both the Class1 and Class2 have the same address for HelloClass::hello(), and it is the address of the function in Class1.C
I'm assuming that this is because when GCC is doing the linking, it sees vtables for classes with the same mangled names and just discards one of them. But should it warn about this? Or even cause an error. I have tried with -Wall and -Wextra but nothing is mentioned.
No, the standard explicitly allows the compiler to silently do the wrong thing in this case.
Explicitly, you are causing Undefined Behavior by having two conflicting definitions for the same decorated name in the same program.
It is called the ODR "One Definiton Rule".
Chapter 3.2.
Use explicit name for namespaces

Run time resolution c++ Namespace conflicts

File1.h
// Declaration
Class A
{
void Func();
}
//Along with some other stuff
File1.cpp
//Definition
A::Func()
{
}
// Along with some other stuff
File2.h
class A
{
void Func();
}
File2.cpp
// Definition
File2::A::Func()
{
}
File3.cpp
#include "File1.h"
#include "File2.h"
//
Invokes Func()
Main1.cpp Main2.cpp
Main1.cpp File3.cpp and File2.cpp are build together
Main1.cpp File3.cpp and File1.cpp are build together
I want to invoke Func() depending different linkage
But, it gives me compile time error.
How should I get around compile time error?
Is there standard way to get around above problem?
If I use namespace for File1 and File2 then I will not be able to
invoke dynamically. Note: I can not change File1.h
Unlike Java (for one example), which enforces a 1:1 correspondence between classes and file names, C++ basically ignores file names completely. As such, to resolve the conflict between your two classes (both named A), you can use namespaces:
//file1.h:
class A
void Func();
};
//file1.cpp:
A::Func() {}
//file2.h:
namespace f2 {
class A {
void Func();
};
}
// file2.cpp:
namespace f2 {
A::Func() {}
}
// main.cpp
#include "file1.h"
#include "file2.h"
int main() {
A f1a;
f2::A f2a;
f1a.Func(); // invokes Func declared in file1.h, which is in global namespace
f2a.Func(); // invokes Func declared in file2.h, which is in namespace f2
return 0;
}
It's not clear what you mean by invoking dynamically. Dynamic invocation sounds a lot like using a polymorphic function, which would require a common base class:
struct base {
virtual void Func() = 0;
};
struct A1 : public base {
virtual void Func() {}
};
struct A2 : public base {
virtual void Func() {}
};
int main() {
A1 a1;
A2 a2;
base *b[2] = { &a1, &a2 };
b[0]->Func(); // invokes A1::Func()
b[1]->Func(); // invokes A2::Func()
return 0;
}