c++ initialize template class constructor - c++

How do I initialize pointer class B foo inside class A? I am new to C++.
Header.h
namespace Core
{
enum type
{
Left, Right
};
template<type t>
class B
{
public:
B(int i);
private:
type dir;
int b = 12;
};
class A
{
public:
B<Left> *foo;
};
}
Source.cpp
namespace Core
{
template<type t>
B<t>::B(int i)
{
dir = t;
b = i;
}
}
int main()
{
Core::A *a = new Core::A;
a->foo = new Core::B<Core::Left>(10);
return 0;
}

Source.cpp needs a #include "Header.h" statement, and Header.h needs a header guard.
Also, you need to move the implemention of B's constructor into the header file. See Why can templates only be implemented in the header file?.
Try this:
Header.h:
#ifndef HeaderH
#define HeaderH
namespace Core
{
enum type
{
Left, Right
};
template<type t>
class B
{
public:
B(int i);
private:
type dir;
int b = 12;
};
class A
{
public:
B<Left> *foo;
};
template<type t>
B<t>::B(int i)
{
dir = t;
b = i;
}
}
#endif
Source.cpp
#include "Header.h"
int main()
{
Core::A *a = new Core::A;
a->foo = new Core::B<Core::Left>(10);
//...
delete a->foo;
delete a;
return 0;
}
I would suggest taking it a step further by inlining B's constructor and giving A a constructor to initialize foo:
Header.h:
#ifndef HeaderH
#define HeaderH
namespace Core
{
enum type
{
Left, Right
};
template<type t>
class B
{
public:
B(int i)
{
dir = t;
b = i;
}
private:
type dir;
int b = 12;
};
class A
{
public:
B<Left> *foo;
A(int i = 0)
: foo(new B<Left>(i))
{
}
~A()
{
delete foo;
}
};
}
#endif
Source.cpp
#include "Header.h"
int main()
{
Core::A *a = new Core::A(10);
//...
delete a;
return 0;
}

How do I initialize pointer class B foo inside class A?
Option 1
Construct a B<Left> with an assumed value.
class A
{
public:
B<Left> *foo = new B<Left>(0);
};
Option 2
Add a constructor of A that accepts an int that can be used to construct a B<Left> .
class A
{
public:
A(int i) : foo(new B<Left>(i)) {}
B<Left> *foo;
};
Word of caution
Before you down too far into using pointers to objects in your classes, consider the following:
What is The Rule of Three?
https://en.cppreference.com/w/cpp/memory, specially shared_ptr and unique_ptr.

Related

Inheriting both class template and the template paraemeter

Suppose we have the following template class, inspired by std::shared_ptr (ignore bad memory management for simplicity):
template <class C> class shared_class {
public:
const shared_class& operator=(const shared_class& rhs) {
ptr = rhs.ptr;
refs[ptr] += 1;
return *this;
}
C* data() { return ptr; }
protected:
shared_class() {
if (ptr == nullptr)
ptr = new C;
refs[ptr] = 1;
}
shared_class(const shared_class& other) {
ptr = other.ptr;
refs[ptr] += 1;
}
~shared_class() {
if ((refs[ptr] -= 1) == 0) {
refs.erase(ptr);
delete ptr;
}
}
private:
static std::unordered_map<C*, size_t> refs;
C* ptr = nullptr;
};
template <class C> std::unordered_map<C*, size_t> shared_class<C>::refs = {};
I would like to use it in the following way:
class A_data {
protected:
int foo = 50;
friend class A;
friend class shared_class<A_data>;
};
class A : protected shared_class<A_data> {
public:
void foo(int f) { data()->foo = h; }
int foo() { return data()->foo; }
};
using namespace std;
int main(){
A a;
A b = a;
a.foo(40);
cout << b.foo(); // 40
}
This works well, but now suppose I want to create a class that inherits A, but also inherits its data, such as this:
class B_data : public A_data {
int bar = 100;
friend class B;
friend class shared_class<B_data> // Probably wrong
};
class B : public A {
int bar() {
return data()->bar(); // Error: no member 'bar' in A_data
}
}
This is a problem, because the constructor in shared_class only knows how to allocate A_data. It seems to me that I am only able to decide on one form of inheritence: either I inherit the template class like above, or I can inherit a different shared_class template, like this:
class B_data : public A_data {
int bar = 100;
friend class B;
friend class shared_class<B_data> // Now it's not wrong
};
class B : public shared_class<B_data> {
int bar() {
return data()->bar(); // Now it will work
}
}
While this works, I lose relation to the A class, and am now unable to do use A::foo, forcing me to define it in B:
class B : public shared_class<B_data> {
void foo(int f) { data()->foo = h; }
int foo() { return data()->foo; }
int bar() { return data()->bar(); }
}
Is there a (relatively elegant) way to make this work as though B inherits A while simultaneously B_data inherits A_data?

How to condense a struct in a class c++?

I have a a.h which has a class d. I am wondering how to make a shorthand way to use the struct 'a' inside of my class.
//a.h
class d
{
public:
struct a
{
int val;
}
};
//a.cpp
#include "a.h"
using d::a; //line with error
a methodName()
{
//does stuff
return object_of_type_a;
}
what about this one
class d
{
public:
struct a
{
int val;
};
};
typedef struct d::a da;

using static_cast to change derived struct member

For my new project, I wanted to use my previous code as framework to speed up prototyping by avoiding rewriting code. In the code below, Derived struct belongs to the new project and it requires to define a new member, MoreElaborateMember which has stuff relevant to the new project. I want to use the function, foo from the base project to make changes on MoreElaborateMember but I can't. How can I solve this problem without touching to the base code?
#include <cassert>
struct SimpleMember
{
int a;
};
struct MoreElaborateMember: SimpleMember
{
// lots of other stuff
};
struct Base
{
SimpleMember member;
};
struct Derived: Base
{
MoreElaborateMember member;
};
void foo(Base& base)
{
base.member.a = -1;
}
int main()
{
Base base;
Derived derived;
foo(static_cast<Base&>(derived));
assert(derived.member.a == -1);
return 0;
}
Have you considered composing MoreElaborateMember from SimpleMember instead of inheriting? Might be a bit of boiler plate but I think it would achieve what you want if I've understood correctly.
struct SimpleMember
{
int a;
};
struct MoreElaborateMember
{
MoreElaborateMember(SimpleMember& s)
: a(s.a)
{}
int& a;
int b;
};
struct Base
{
SimpleMember member;
};
struct Derived : public Base
{
Derived()
: Base()
, member(Base::member)
{}
MoreElaborateMember member;
};
void foo(Base& base)
{
base.member.a = -1;
}
int main(int, char**)
{
Derived derived;
derived.member.a = 13;
derived.member.b = 42;
assert(derived.member.a == 13);
assert(derived.member.b == 42);
foo(derived);
assert(derived.member.a == -1);
assert(derived.member.b == 42);
return 0;
}
You will be more comfortable if you use polymorphism.
#include <cassert>
struct SimpleMember
{
int a;
};
struct MoreElaborateMember : SimpleMember
{
// lots of other stuff
};
struct Base
{
protected:
SimpleMember member;
public:
virtual void set_member(int m) = 0;
};
struct Derived : public Base
{
MoreElaborateMember member;
virtual void set_member(int m)
{
Base::member.a = m;
member.a = m;
}
};
void foo(Base* base)
{
base->set_member(-1);
}
int main()
{
Derived derived;
foo(&derived);
assert(derived.member.a == -1);
return 0;
}

Can i make a define constructor which contains an object from another class?

Can I do an defined constructor which contains an object from another class?
If i can do how is defined.
this is an example.I do classes and how could be defined the constructor of class "Abonati" which contains an object "abonament"
I need that because i have another class which contain a vector of "abonati"
#pragma once
#include"abonament.h"
#include<iostream>
#include<vector>
using namespace std;
class abonati
{
char*nume_abonat;
int nr_telefon;
char *numefisier;
abonament *a;
public:
abonati();
abonati(char*, int , char *,abonament *);
abonati(abonati&a);
void Send();
~abonati();
};
`#pragma once
#include"abonati.h"
class abonament
{
protected:
int cost;
public:
abonament();
abonament(int costa);
virtual ~abonament();
};
#include "abonament.h"
abonament::abonament()
{
this->cost = 0;
}
abonament::abonament(int costa)
{
this->cost = costa;
}
abonament::~abonament()
{
}
`
I guess you would like to pass an class instance to another class constructor
Here is an example
#include <iostream>
class A
{
public:
A(int value) : m_int(value) {}
int GetInt() { return m_int; }
private:
int m_int;
};
class B
{
public:
B(A& a) : m_int(a.GetInt()) {} // Here constructor expects instance of class A
int GetInt() { return m_int; }
private:
int m_int;
};
int main()
{
A a(2);
B b(a); // Pass an object of class A to constructor of class B
std::cout << b.GetInt() << std::endl;
return 0;
}
Prints
2

How do I avoid forward declarations?

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)