Multiclassing

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <iostream>
#include <string>

struct Class {};

struct A : virtual public Class {
	int num;
	A (int n) : num(n) {std::cout << "A::num = " << num << std::endl;}
};

struct B : virtual public Class {
	int num;
	double dub;
	B (int n) : num(n) {std::cout << "B::num = " << num << std::endl;}
	B (int n, double d) : num(n), dub(d) {std::cout << "B::num = " << num << ", dub = " << d << std::endl;}
};

struct C : virtual public Class {
	int num;
	std::string str;
	C (int n) : num(n) {std::cout << "C::num = " << num << std::endl;}
	C (int n, const std::string& s) : num(n), str(s) {std::cout << "C::num = " << num << ", str = " << str << std::endl;}
};

template <typename T> struct Base {};
template <> struct Base<A> : public A {using A::A;};
template <> struct Base<B> : public B {using B::B;};
template <> struct Base<C> : public C {using C::C;};

template <typename... T>
struct Multiclass : virtual public Base<T>... {  // variadic base list, working as intended
	Multiclass (int n) : Base<T>(n)... {}  // variadic member initializer list, but useless in this case
	template <typename... ARGS>
	Multiclass (ARGS... args) {}  // How to handle the general case???  Pack expansion of some sort?
};



int main() {
	Multiclass<A,B,C> a(5);  // This doesn't help much.  How to get the lines below to work?
//	Multiclass<A,B,C> b(1, 2, 4.1, 3, "Hi");  // Call up constructors of A, B, C.
//	Multiclass<C,B,A> c(3, "Hi", 2, 4.1, 1); // Call up constructors of C, B, A.
//	Multiclass<A,C> d(5, 3, "Hi"); // Call up constructors of A, C.
}


Motivation: Suppose I have classes Singer, TennisPro, Sprinter, Politician, Cop, Teacher, ... I want to be able to multi-class any of these of any size. So for example,
Multiclass<Singer, Sprinter, Teacher>
is a class that does everything that Singer, Sprinter, Teacher do. Given many classes, it is just impossible to define multiclasses individually for any combination of the classes. So I figured the above idea should one good approach, but I cannot figure out the constructor and such. Or is there a better approach altogether to define any multiclass of any combination of a given set of classes?
Last edited on
I don't understand why you want this. Just derive classes normally.
Last edited on
Or perhaps I should try this design?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <iostream>
#include <string>

struct Class {};

struct A : virtual public Class {
	void fooA() {std::cout << "fooA() called." << std::endl;}
};

struct B : virtual public Class {
	void fooB() {std::cout << "fooB() called." << std::endl;}
};

struct C : virtual public Class {
	void fooC() {std::cout << "fooC() called." << std::endl;}
};

struct Multiclass : Class {
	A* a = nullptr;
	B* b = nullptr;
	C* c = nullptr;
	// etc... for ALL concrete derived class of Class.
//	Multiclass (A* a, B* b, C* c) : a(a), b(b), c(c) {}  // Too many permutations to deal with!
//	Multiclass (A* a, C* c) : a(a), c(c) {}
//	Multiclass (B* b, C* c) : b(b), c(c) {} 
	void setA (A* _a) {a = _a;}
	void setB (B* _b) {b = _b;}
	void setC (C* _c) {c = _c;}
	// etc... set each type manually to construct the MultiClass.
	
	// ALL functions of A, B, C, ... defined here!  Even if the particular Multiclass does not have all of A,B,C...
	void fooA() {a->fooA();}
	void fooB() {b->fooB();}
	void fooC() {c->fooC();}  // If c == nullptr, then this Multiclass object shall simply never call fooC().  Design is fine?
	// etc...
	void chooseAction() {
		std::cout << "What would you like to do?" << std::endl;
		if (a) std::cout << "-Call fooA()." << std::endl;
		if (b) std::cout << "-Call fooB()." << std::endl;
		if (c) std::cout << "-Call fooC()." << std::endl;
	}	
};

int main() {
	Multiclass m;
	m.setA (new A);
	m.setB (new B);  // Lousy way to instantiate m, but constructor problem handled at least.

//	m.fooC();  // Without knowing anything about m (which is just Multiclass), need to somehow make sure m never calls fooC().
	// In fact, the client must know in advance that m cannot call fooC().  By checking that m.c == nullptr???
	m.chooseAction();
}

/*
Output:

What would you like to do?
-Call fooA().
-Call fooB().
*/
Last edited on
It's the virtual inheritance we're struggling with. Why?
No, it's not the virtual inheritance that confuses me. It's why you want to have this template at all - if you don't plan to ever derive it then why does it exist? if you do plan to derive it then why bother with ctors when they won't be used? Just make a new class on an as-needed basis.
Last edited on
Topic archived. No new replies allowed.