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;
}
Related
i have a class in c++ that i want to convert to a namespace
i have tried to look around in google but i couldn't find any solution that will make my class a namespace.
how do i do that? its a class that contains 3 functions.
for example:
class c
{
public:
void A();
void B();
void X();
}
i want to be able to use these functions without creating a new object of the class, i want to to be a namespace.
class C that has functions a(),b(),x(), will turn into a namespace.
p.s, i have CLion 2017
ty
It's much easier than you think.
namespace c
{
void A();
void B();
void X();
}
You probably want something like this:
foo.cpp
#include "bar.h"
int main()
{
bar::A();
bar::B();
}
bar.h
namespace bar
{
void A();
void B();
}
bar.cpp
#include "bar.h"
namespace bar
{
void A()
{
...
}
void B()
{
..
}
}
This is a minimal example without header guards for brevity.
You may want to use static functions
class MyClass
{
public:
static void A();
}
You then may call those functions like this :
MyClass::A();
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
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.
How can I access test.a from main?
Here is my code:
myfile1.cpp:
#include "myfile2.h"
int main()
{
test.a=1; //this gives error "incomplete type is not allowed"
}
myfile2.h:
class abc;
abc test;
myfile2.cpp:
#include "myfile2.h"
class abc{
public:
int a;
abc():
a(0){}
} test;
You cannot define a variable of incomplete type, but you can declare one. If you don't want to make the class definition public, then you cannot access class members outside the translation unit where you define the class, so you also need to provide accessors. Here's a possible approach:
header.h:
class abc; // declares the name "abc"
extern abc test; // declares the name "test"
void set_a(abc & obj, int val); // declares the name "set_a"
impl.cpp:
#include "header.h"
class abc { /* definition */ };
abc test;
void set_a(abc & obj, int val) { obj.a = val; }
main.cpp:
#include "header.h"
int main()
{
set_a(test, 1);
}
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