How do I avoid forward declarations? - c++

Let's say I have two classes, A and B:
class B;
class A
{
private:
int an_int;
B *something_else;
public:
A(int n) : an_int(n), something_else(nullptr) {}
};
class B
{
private:
int an_int;
A *something_else;
public:
B(int n) : an_int(n), something_else(nullptr) {}
};
How can I make it so that I don't have to prototype B in order to have a pointer to a B object in class A?

This solution is most probably what is intended in an exercise about inheritance where you can't use a forward declaration.
Instead of the forward declaration
class B;
you can define an interface like
struct I_whoop
{
virtual void whoop_whoop() = 0;
};
then let class B implement that interface, and just use a pointer to the interface.

Actually You can not if using concrete class.
But You can achieve your goal by using template parameters. Making class B a template parameter of template class A.

How can I make it so that I don't have to prototype B in order to have a pointer to a B object in class A?
Like this:
class A
{
private:
int an_int;
class B *something_else;
public:
A(int n) : an_int(n), something_else(nullptr) {}
};
class B
{
private:
int an_int;
class A *something_else;
public:
B(int n) : an_int(n), something_else(nullptr) {}
};
In C and C++ it has never been necessary for a type T to be
forward declared before the declaration of objects of type T *
(or const variants), because the declaration of a T * per se requires
the compiler only to know the size of a T *, not the size or definition
of a T, and the size of a T * is the same, regardless of T.
Here is a more fleshed-out illustration:
class A
{
private:
int an_int;
class B *something_else;
public:
A(int n, class B * pb = nullptr) : an_int(n), something_else(pb) {}
int get_int() const {
return an_int;
}
void set_B(class B * pb) {
something_else = pb;
}
class B * get_B() const {
return something_else;
}
};
class B
{
private:
int an_int;
class A *something_else;
public:
B(int n, class A * pa = nullptr) : an_int(n), something_else(pa) {}
int get_int() const {
return an_int;
}
void set_A(class A * pa) {
something_else = pa;
}
class A * get_A() const {
return something_else;
}
};
#include <iostream>
int main()
{
A a(1);
B b(2);
a.set_B(&b);
b.set_A(&a);
std::cout << a.get_B()->get_int() << std::endl;
std::cout << b.get_A()->get_int() << std::endl;
return 0;
}
Output:
2
1
(gcc 4.9.2/clang 3.5.2 -std=c++11 -Wall -pedantic)

Related

How to Merge two classes A and B to define the functions of a abstract class in C++

In my C++ project, I have an abstract class that defines an interface for a dll. Call it CAbstractClass.
I have a class AClass which has defined functions for all but 1 of the functions of CAbstractClass. How do I create a new non-abstract class C to inherit CAbstractClass?
Here's my attempt. It results in the error 'E0322: object of abstract class type "CClass" is not allowed.
#include "stdafx.h"
class CAbstractClass
{
public:
CAbstractClass(void) {};
~CAbstractClass(void) {};
virtual int Fn1(int a) = 0;
virtual double Fn2(int a, int b) = 0;
virtual int Fn3(double a, double b) = 0;
};
class AClass
{
public:
AClass(void) {};
~AClass(void) {};
int Fn1(int a) { return 2 * a; }
double Fn2(int a, int b) { return (double)a / (double)b; }
};
class BClass
{
public:
BClass(void) {};
~BClass(void) {};
int Fn3(double a, double b) { return (int) (a+b); }
};
// My guess at how to combine all the classes.
class CClass : public CAbstractClass, public AClass, public BClass
{
public:
CClass(void) {};
~CClass(void) {};
};
int main()
{
CClass C; // E0322: object of abstract class type "CClass" is not allowed.
return 0;
}
AClass and BClass also have to inherit from CAbstractClass. Fn1 Fn2 and Fn3 just don't implement virtual methods of abstract class so CClass is also abstract
class AClass : public CAbstractClass {
//...
};
class BClass : public CAbstractClass {
//...
};
class CClass : public virtual AClass, public virtual BClass {
//...
};
I'm not sure if it can be done using a single CAbstractClass, but if you split your abstract interface into two separate abstract interfaces, then it is easy enough:
#include <stdio.h>
class CAbstractClassA
{
public:
virtual int Fn1(int a) = 0;
virtual double Fn2(int a, int b) = 0;
};
class CAbstractClassB
{
public:
virtual int Fn3(double a, double b) = 0;
};
class AClass : public CAbstractClassA
{
public:
int Fn1(int a) { return 2 * a; }
double Fn2(int a, int b) { return (double)a / (double)b; }
};
class BClass : public CAbstractClassB
{
public:
int Fn3(double a, double b) { return (int) (a+b); }
};
// My guess at how to combine all the classes.
class CClass : public AClass, public BClass
{
public:
};
int main()
{
CClass C;
printf("Fn1(5) returns %i\n", C.Fn1(5));
printf("Fn2(10,12) returns %f\n", C.Fn2(10,12));
printf("Fn3(3.14,6.28) returns %i\n", C.Fn3(3.14,6.28));
return 0;
}
Here's what I ended up using. I chose it because it leaves AClass alone. There is more work: every member function that comes from AClass must be defined in BClass. Another benefit is that there's no need for a CClass.
#include "stdafx.h"
class BAbstractClass
{
public:
BAbstractClass(void) {};
~BAbstractClass(void) {};
virtual int Fn1(int a) = 0;
virtual double Fn2(int a, int b) = 0;
virtual int Fn3(double a, double b) = 0;
};
class AClass
{
public:
AClass(void) {};
~AClass(void) {};
int Fn1(int a) { return 2 * a; }
double Fn2(int a, int b) { return (double)a / (double)b; }
};
class BClass : public AClass, public BAbstractClass
{
public:
BClass(void) {};
~BClass(void) {};
int Fn3(double a, double b) { return (int)(a + b); }
// Define a function for each of AClass' member functions.
int Fn1(int a) { return AClass::Fn1(a); }
double Fn2(int a, int b) { return AClass::Fn2(a, b); }
};
int main()
{
BClass B;
return 0;
}

Multiple "level" derived abstract classes with

I have a problem in C++ where I have
One abstract base class with common members and pure virtual functions. This is A in the code below.
Multiple derived classes with different members and functions. This is B and C in the code below.
Multiple derived classes that implements the virtual functions and has no new members. This is do_stuff_1 and do_stuff_2 in the code below.
My solution so far is to mix templates and abstract classes. The goal is to hold a pointer to the abstract classes B orC and call do_stuff. My questions are
Is my solution a good one?
If not, are there better solutions?
If so, are there some pitfalls I should be aware of?
Here is my solution so far
#include <iostream>
#include <memory>
/* base virtual class */
class A {
public:
int a;
A(int a) : a(a) {}
virtual void do_stuff() = 0;
};
/* concrete implementations of do_stuf */
template<class T>
class do_stuff_1 : public T {
public:
using T::T;
void do_stuff(){
std::cout << "do_stuff_1 " << this->a << std::endl;
}
};
template<class T>
class do_stuff_2 : public T {
public:
using T::T;
void do_stuff(){
std::cout << "do_stuff_2 " << this->a + 1 << std::endl;
}
};
/* derived classes from A */
class B : public A {
public:
int b; // one member here but many more in my application
B(int a, int b): A(a), b(b) {}
};
class C : public A {
public:
std::string c; // one member here but many more in my application
C(int a, std::string c): A(a), c(c) {}
};
int main() {
std::unique_ptr<B> x;
x.reset(new do_stuff_1<B>(1, 1));
x->do_stuff();
std::cout << x->b << std::endl;
x.reset(new do_stuff_2<B>(1, 2));
x->do_stuff();
std::cout << x->b << std::endl;
std::unique_ptr<C> z;
z.reset(new do_stuff_1<C>(1, "Yo"));
z->do_stuff();
std::cout << z->c << std::endl;
z.reset(new do_stuff_2<C>(1, "Hello"));
z->do_stuff();
std::cout << z->c << std::endl;
return 0;
}
The result is
do_stuff_1 1
1
do_stuff_2 2
2
do_stuff_1 1
Yo
do_stuff_2 2
Hello
Your solution seems fine. It's a compile time approach and you create 4 different objects.
The main drawbacks are:
you won't know if the do_stuff() code is correct unless you instantiate the template.
you could instantiate do_stuff_1 or do_stuff_2 with classes which are not of base class A. You should at least use override in the template to make sure it overrides a virtual function.
Here a small improvement to address these issues:
template<class T>
class do_stuff_2 : public T {
public:
using T::T;
void do_stuff() override {
static_assert (std::is_base_of<A, T>::value, "T should be derived from A");
std::cout << "do_stuff_2 " << this->a + 1 << std::endl;
}
};
By the way, using make_unique would be nice.
To me looks like some kind of policy, this may look like:
#include <iostream>
#include <memory>
#include <type_traits>
struct AwayToDoTheStuff {
virtual void operator()(int a) = 0;
virtual ~AwayToDoTheStuff() {}
};
/* concrete implementations of do_stuf */
class HowToDoStuff1 : public AwayToDoTheStuff {
public:
void operator()(int a) override {
std::cout << "do_stuff_1 " << a << std::endl;
}
};
class HowToDoStuff2 : public AwayToDoTheStuff {
public:
void operator()(int a) override {
std::cout << "do_stuff_2 " << a + 1 << std::endl;
}
};
/* base virtual class */
template <class HowToDoStuff>
class A {
public:
int a;
A(int a) : a(a) {}
void do_stuff() {
static_assert(std::is_base_of<AwayToDoTheStuff, HowToDoStuff>::value);
HowToDoStuff()(a);
}
};
/* derived classes from A */
template <class HowToDoStuff>
class B : public A<HowToDoStuff> {
public:
int b; // one member here but many more in my application
B(int a, int b): A<HowToDoStuff>(a), b(b) {}
};
template <class HowToDoStuff>
class C : public A<HowToDoStuff> {
public:
std::string c; // one member here but many more in my application
C(int a, std::string c): A<HowToDoStuff>(a), c(c) {}
};
int main() {
B<HowToDoStuff1>(1, 1).do_stuff();
B<HowToDoStuff2>(1, 2).do_stuff();
C<HowToDoStuff1>(1, "Yo").do_stuff();
C<HowToDoStuff2>(1, "Hello").do_stuff();
return 0;
}
but I must say this is quite hard to tell if a solution match well with an example that much generic. I hope it will help you in some ways...
EDIT:
You seem to need to have a common base class so that you can pass your objects B and C to a common function of the kind void f(A &a);
Then my example can be adapted that way:
/* base virtual class */
class A {
public:
void do_stuff() = 0;
};
template <class HowToDoStuff>
class Policy_A : public A {
public:
int a;
A(int a) : a(a) {}
void do_stuff() override {
static_assert(std::is_base_of<AwayToDoTheStuff, HowToDoStuff>::value);
HowToDoStuff()(a);
}
};
/* derived classes from A */
template <class HowToDoStuff>
class B : public Policy_A<HowToDoStuff> {
public:
int b; // one member here but many more in my application
B(int a, int b): Policy_A<HowToDoStuff>(a), b(b) {}
};
template <class HowToDoStuff>
class C : public Policy_A<HowToDoStuff> {
public:
std::string c; // one member here but many more in my application
C(int a, std::string c): Policy_A<HowToDoStuff>(a), c(c) {}
};
So that the do_stuff can be called on opaque A objects.
You may also pass the HowToDoStuff object at creation:
/* base virtual class */
class A {
std::unique_ptr<AwayToDoTheStuff> _stuffer;
public:
int a;
A(std::unique_ptr<AwayToDoTheStuff> stuffer, int a) : _stuffer(std::move(stuffer)), a(a) {}
void do_stuff() {
(*_stuffer)(a);
}
};
/* derived classes from A */
class B : public A {
public:
int b; // one member here but many more in my application
B(std::unique_ptr<AwayToDoTheStuff> &stuffer, int a, int b): A(std::move(stuffer), a), b(b) {}
};
class C : public A {
public:
std::string c; // one member here but many more in my application
C(std::unique_ptr<AwayToDoTheStuff> &stuffer, int a, std::string c): A(std::move(stuffer), a), c(c) {}
};
int main() {
auto stuffer1forB = std::unique_ptr<AwayToDoTheStuff>(new HowToDoStuff1);
auto stuffer2forB = std::unique_ptr<AwayToDoTheStuff>(new HowToDoStuff2);
B(stuffer1forB, 1, 1).do_stuff();
B(stuffer2forB, 1, 2).do_stuff();
auto stuffer1forC = std::unique_ptr<AwayToDoTheStuff>(new HowToDoStuff1);
auto stuffer2forC = std::unique_ptr<AwayToDoTheStuff>(new HowToDoStuff2);
C(stuffer1forC, 1, "Yo").do_stuff();
C(stuffer2forC, 1, "Hello").do_stuff();
return 0;
}

classes in c++ and virtual funct

I want to create 2 kind of classes.
the classes will have similar function "set", but the set funct will get "int" in class B and double in class C. (A is abstract calss but it does not require).
What do I need to do?
class A{
int x;
public:
A (int t=1): x(t){}
virtual void set ()=0;
}
class B: public A{
int y;
public:
virtual void set (int y);
};
class C: public A{
double y;
public:
virtual void set (double y);
};
void main ()
{
B b; //error
C c; //error
}
Create a single template class and instantiate which ever you need at the time, or typedef B and C from the template class:
template< typename T > class A
{
public: A() : mValue() {}
void Set( T value ) { mValue = value; }
private: T mValue;
};
typedef A< int > B;
typedef A< double > C;
There are pretty many variants to solve this, but first of all, virtual function has to have the same signature (there could be an exception, but that's irrelevant for your case). So solution is to have and argument(s) that will solve all cases. There are variants:
Pass all variants to the function, and use only particular one:
class A {
public:
virtual void set( int, double ) = 0;
};
class B {
int y;
public:
virtual void set( int val, double ) { y = val; }
};
class C {
double y;
public:
virtual void set( int , double val ) { y = val; }
};
This is not very good solution and does not scale well, so we can use union:
Union Arg {
int i;
double d;
};
class A {
public:
virtual void set( Arg a ) = 0;
};
// derived classes are trivial, so omitted
Union is not type safe, so we can use boost::variant instead
Another solution to have another hierarchy for parameter:
struct Arg {
virtual ~Arg();
};
struct IntArg : Arg {
int m_value;
};
struct DoubleArg : Arg {
double m_value;
};
class A {
virtual void set( const Arg &a ) = 0;
};
class B {
int y;
public:
virtual void set( const Arg &a ) { y = dynamic_cast<const IntArg &>( a ).m_value; }
};
class C {
double y;
public:
virtual void set( const Arg &a ) { y = dynamic_cast<const DoubleArg &>( a ).m_value; }
};
You can use static_cast and then you will not need virtual destructor in Arg, but that is less safe.
These are only some variants, there could be much more, which one suits you best you can only decide based on your program requirements.
Ditch the inheritance and virtual thing. You can't easily access a statically unknown type result via a virtual function. So:
class A
{
private:
int x_;
public:
A( int const t = 1 ): x_( t ) {}
};
class B
: public A
{
private:
int y_;
public:
void set( int const y );
};
class C
: public A
{
private:
double y_;
public:
void set( double const y );
};
int main ()
{
B b; // OK
C c; // OK
}
Note the semicolon at the end of class A and the int main instead of void main.
Such details matter.
Otherwise you can send people who want to help you, on long wild goose chases. And you don't want that, do you? So, make sure the code you post has been accepted by a compiler, except possibly for the troublesome parts that you want to show do not compile.
The trick is to find common parts of B and C, and put them to base class. The stuff that is different should go to constructor parameter of the derived class:
class A {
virtual std::string get() const=0;
virtual void set(std::string s)=0;
};
class B : public A { B(int a) : a(a) { } int a; };
class C : public A { C(float b) : b(b) { } float b; }
To implement the functions, you'll need the following:
void B::set(std::string s) {
stringstream ss(s);
ss >> a;
}
void C::set(std::string s) {
stringstream ss(s);
ss >> b;
}
The functions look the same, but are actually calling different operator>>.

Leaking attributes of class to it's components

I've got the following classes:
class A {
// Whatever
};
class B {
T attribute;
A a;
};
Now suppose i have the following scenario:
A aX, aY;
B bX, bY;
Now i can sort of "insert" aX or aY into bX or bY.
I would like for the objects of type A to know, what B they are in, or in other words, what is the "attribute" of their "superclass" B.
Question:
I would like to be able to move the objects of type A freely between their "superclasses" B and i need a way to leak the attribute of B to them dynamically at runtime, so the objects of type A always know, what B they belong to (or what is the attribute of B they are currently in).
What is the best way to do it ?
Perhaps this is useful (pointer from the owner to the attribute, and the reverse):
class A;
class B {
T attribute;
A* a;
public:
void setA(A* newA);
T getAttribute() {return attribute;}
void setAttribute() {/*some code*/}
};
class A {
B* Owner;
friend void B::setA(A* newA);
public:
void setOwner(B* newOwner) {
newOwner->setA(this);
}
};
void B::setA(A* newA)
{
A* tempA = this->a;
B* tempB = newA->Owner;
tempA->Owner = NULL;
tempB->a = NULL;
this->a = newA;
newA->Owner = this;
}
UPDATED: Fixed a bug in cycle-pointing and cycle-calling, it could be solved only with a friend function.
One thing you could to is give A a pointer to it's B "parent":
class A {
public:
A() : b_(0) {}
explicit A(B* parent) : b_(parent) {}
private:
B* b_;
};
class B {
B() : a(this) {}
};
Define "B" class as interface. Make "getAttribute" method and set pointer of "B" to "A" class's instance. Now you can make child's of "B" class and add "A" classes to them and "A" class can always know attribute of "B".
class A
{
// Whatever
B* pointerToB;
void setB(B* b){ pointerToB = b; }
};
class B
{
virtual void someMethod() = 0;
void addA(A* a)
{
a->setB(this);
this->a = *a;
}
T getAttribute(){ return attribute; }
T attribute;
A a;
};
class BB : public B {} // define BB's someMethod version or more method's
You could set a pointer to B in A and use a reference to A in B to get waht you want directly from an A object:
#include <iostream>
class B;
class A {
B *_b;
public:
void setB(B *b) {
_b = b;
}
B *getB() {
return _b;
}
};
class B {
int _attribute;
A &_a;
public:
B(A& a, int attribute) : _attribute(attribute), _a(a) {
_a.setB(this);
}
int getAttribute() {
return _attribute;
}
};
int main(int argc, const char *argv[])
{
A a1;
B b1(a1, 5);
A a2;
B b2(a2, 10);
std::cout << a1.getB()->getAttribute() << std::endl;
std::cout << a2.getB()->getAttribute() << std::endl;
return 0;
}
Output:
5
10

How to hide a datum from everyone but class T

I want a type A that will yield its hidden datum to an object of type T but hide the datum from everyone else. My C++ compiler happens to be GCC 4.4, but that shouldn't matter. Why won't this work?
#include <iostream>
template <class T> class A {
private:
int n1;
public:
friend class T;
A(const int n0 = 0) : n1(n0) {}
};
class B {
public:
int f(const A<B> a) const { return a.n1; }
B() {}
};
int main() {
const A<B> a(5);
const B b;
const int m = b.f(a);
std::cout << m << "\n";
return 0;
}
Incidentally, this works fine, except that it fails to hide the datum:
#include <iostream>
template <class T> class A {
private:
int n1;
public:
int n() const { return n1; }
A(const int n0 = 0) : n1(n0) {}
};
class B {
public:
int f(const A<B> a) const { return a.n(); }
B() {}
};
int main() {
const A<B> a(5);
const B b;
const int m = b.f(a);
std::cout << m << "\n";
return 0;
}
Does C++ really not allow a friend class to be specified at compile time as a template parameter? Why not? If not, then what alternate technique should I use to hide the datum? (One would prefer a compile-time technique if possible.)
What is my misunderstanding here, please?
(I see some answers to related questions here and here, but either they don't answer my particular question or I fail to understand that they do so. At any rate, maybe I am using the wrong technique altogether. Though I remain interested in why the friend class T fails, what I really want to know is how to hide the datum, whether with a friend or by other means.)
Thanks.
Your compiler is simply too old. C++11 allows you to declare template parameters as friends.
§11.3 [class.friend] p3
A friend declaration that does not declare a function shall have one of the following forms:
friend elaborated-type-specifier ;
friend simple-type-specifier ;
friend typename-specifier ;
If the type specifier in a friend declaration designates a (possibly cv-qualified) class type, that class is declared as a friend; otherwise, the friend declaration is ignored.
And it even contains an example of a template parameter as a friend:
class C;
// [...]
template <typename T> class R {
friend T;
};
R<C> rc; // class C is a friend of R<C>
R<int> ri; // OK: "friend int;" is ignored
C++03 sadly has no way to do this, however you can simply friend a single free function and let that act as "glue" code that takes the data from one class and passes it to the other. Another way might be the passkey pattern.
I don't know the standardese behind your error (refer to Xeo's answer), but I did find a workaround for C++03.
Instead of making T a friend, make one of T's member functions a friend:
#include <iostream>
template <class T> class A {
private:
int n1;
public:
friend int T::getN1(const A& a) const;
A(const int n0 = 0) : n1(n0) {}
};
class B {
public:
int f(const A<B> a) const { return getN1(a); }
B() {}
private:
int getN1(const A<B>& a) const {return a.n1;}
};
class C {
public:
int f(const A<B> a) const { return getN1(a); }
C() {}
private:
// Error, n1 is a private member of A<B>
int getN1(const A<B>& a) const {return a.n1;}
};
int main() {
const A<B> a(5);
const B b;
const int m = b.f(a);
std::cout << m << "\n";
return 0;
}
Alternatively, you can make a nested class/struct of T be a friend of A. This may be more convenient if there are several private members of A that you want T to have access to.
#include <iostream>
template <class T> class A {
private:
int n1;
public:
friend class T::AccessToA;
A(const int n0 = 0) : n1(n0) {}
};
class B {
public:
int f(const A<B> a) const { return AccessToA::getN1(a); }
B() {};
private:
friend class A<B>;
struct AccessToA
{
static int getN1(const A<B>& a) {return a.n1;}
};
};
class C {
public:
int f(const A<B> a) const { return AccessToA::getN1(a); }
C() {};
private:
friend class A<C>;
struct AccessToA
{
// Error, n1 is a private member of A<B>
static int getN1(const A<B>& a) {return a.n1;}
};
};
int main() {
const A<B> a(5);
const B b;
const int m = b.f(a);
std::cout << m << "\n";
return 0;
}