Accessing variables from one class to another in C++ - c++

I am trying to access a variable declared in class A from class B, without using static variables. I have the classes separated in header and source files.
I have seen different people using pass by reference (I assume "const &a" declared in the class definition) but it doesn't work for me.
Update:When I tried to pass in the A object to the B::print as a const-reference parameter I got an error. In my example, I am trying to access string a from the function void print declared in class B. The problem now is that I am getting an error in B.cpp.
main.cpp
#include <iostream>
#include <string>
#include "A.h"
#include "B.h"
using namespace std;
int main()
{
A first;
B second;
second.print(cout, first);
return 0;
}
A.h
#include <string>
using namespace std;
class A
{
string a = "abc";
public:
A();
void print(ostream& o) const;
~A();
};
A.cpp
#include <iostream>
#include <string>
#include "A.h"
#include "B.h"
using namespace std;
A::A()
{
}
A::~A()
{
}
void A::print(ostream& o) const
{
o << a;
}
ostream& operator<<(ostream& o, A const& a)
{
a.print(o);
return o;
}
B.h
#include <iostream>
#include <string>
#include "A.h"
using namespace std;
class B
{
public:
B();
void print(ostream&, A const&) const;
~B();
};
B.cpp
#include "B.h"
#include "A.h"
#include <iostream>
#include <string>
using namespace std;
B::B()
{
}
B::~B()
{
}
void B::print(ostream& o, A const& a) const
{
o << a << endl;
//^^ error no operator "<<" mathes these operands
}

Since a is not a static member, it can't be accessed without an instance of class A. You can, however, pass one in the function:
class B {
void print(const A &o) {
cout << o.a << endl;
}
};
In addition, if a member is private, you can declare class B as friend, which means it can access private and protected members of class A.
class A {
friend class B;
private:
std::string a = "abc";
};

The way I'd do it is to pass in the A object to the B::print as a const-reference parameter. I'd also pass in the ostream as a reference parameter. And I'd take advantage of C++'s streaming output operator (<<).
Like this:
#include <iostream>
#include <string>
using std::cout;
using std::endl;
using std::ostream;
using std::string;
class A
{
std::string s = "abc";
public:
void print(ostream& o) const;
};
void A::print(ostream& o) const
{
o << s;
}
ostream& operator<<(ostream& o, A const& a)
{
a.print(o);
return o;
}
class B
{
public:
void print(ostream&, A const&) const;
};
void B::print(ostream& o, A const& a) const
{
o << a << endl;
}
int main()
{
A first;
B second;
second.print(cout, first);
}
UPDATE: given the comments above, I'm not not sure if the problem is "How does one split up code into separate .h and .cpp files?" or if it is "How do I access A member variables from B, without using static variables in A?"
UPDATE: I changed A's member variable from a to s to disambiguate from other a identifiers.

Related

Why my random function always not undeclared?

I'm writing my code on linux . But g++ always tells me"Use of undeclared identifier 'random'".I don't know why I have declare it in "Myvector.h"
my code is like :
Myvector.h
class MyVector {
private:
std::vector<double> data;
const int N;
static bool _bDim;
public:
MyVector(); //默认初始化
MyVector(int a); //设置维度初始化
MyVector(std::initializer_list<double> list);
~MyVector();
double &operator[](int);
MyVector &operator=(const MyVector a) {
MyVector b(outN(a));
this->data = a.data;
return *this;
};
friend MyVector random(int a);
}
#endif // MYVECTOR_H_
Myvector.cpp
#include "Myvector.h"
#include <cstdlib>
#include <iostream>
#include <math.h>
#include <time.h>
using namespace std;
bool MyVector::_bDim = true;
MyVector::MyVector() : N(3) {
data = vector<double>(N, 0.0);
_bDim = false;
};
MyVector::MyVector(int a) : N(a) {
data = vector<double>(N, 0.0);
_bDim = false;
};
MyVector::MyVector(std::initializer_list<double> list) : N(list.size()) {
for (auto i = list.begin(); i != list.end(); i++) {
data.push_back(*i);
}
};
MyVector::~MyVector(){
};
double &MyVector::operator[](int i) { return data[i]; }
MyVector random(int a){
MyVector u(a);
srand(time(NULL));
for(int i=0;i<a;i++){
u[i]=rand();
}
return u;
}
main.cpp
#include "Myvector.h"
#include <iostream>
#include<cstdlib>
#include<math.h>
#include <time.h>
using namespace std;
int main(){
MyVector z=random(1);
return 0;}
In fact ,I just know nothing about it. Is there someone going to help me?Thank you.
Below is nothing meaningful. I just need more words to ask this problem.
In the main function of the main.cpp file the following function is called:
MyVector z=random(1);
This appears to be a function which takes a single int argument. Additionally, there is such a function defined in the Myvector.cpp but not declared in Myvector.h (i.e., the main.cpp file does not see any function declaration for the definition).
Update the Myvector.h header to declare the MyVector random(int a) function. Also, the friend declaration is for a random function with 2 parameters, which doesn't look right.
You have to declare the function random somewhere, e.g.
#include "Myvector.h"
#include <iostream>
#include<cstdlib>
#include<math.h>
#include <time.h>
using namespace std;
MyVector random(int);
int main(){
MyVector z=random(1);
return 0;
}
The problem is random in your main function. That one is not declared.
Declaring a friend function means that function has access to the class as if it were a method. It doesn't declare the function at any time, just allows it inside the class.
Your random function is defined is some header file you have included. In your error message you see the return type of random is long int. And you have declared it as MyVector. I am not sure if math.h or time.h have it.
Solution 1: Change the name of your function.
Solution 2: Put your function in a namespace in order to avoid name ambiguity.

error: no matching function for call to 'std::reference_wrapper<Medium>::reference_wrapper()

Book and Article are derived classes from Medium.
Why am I getting this error when trying to insert Medium / Book / Article in the bibliography?
error: no matching function for call to '**std::reference_wrapper<Medium>::reference_wrapper()**
main.cc
#include <iostream>
using namespace std;
#include "Bibliography.h"
#include "Medium.h"
#include "Book.h"
#include "Article.h"
int main()
{
Bibliography p(1);
Medium m1("PN","I","Pasol nah",2017);
p.insert(m1);
cout << p;
return 0;
}
Bibliography.h
#ifndef BIBLIOGRAPHY_H_
#define BIBLIOGRAPHY_H_
#include "Medium.h"
#include "Article.h"
#include "Book.h"
#include <iostream>
#include <functional>
#include <vector>
class Bibliography
{
private:
int m_Size;
std::vector<std::reference_wrapper<Medium>> v;
int index;
public:
Bibliography(int size);
void insert(Medium m);
friend std::ostream& operator<<(std::ostream& out, const Bibliography &b1);
};
#endif
Bibliography.cc
#include "Bibliography.h"
Bibliography::Bibliography(int size)
{
std::cout << "Bibliography created \n";
m_Size = size;
v.resize(m_Size);
index = 0;
}
void Bibliography::insert(Medium m)
{
v.push_back(m);
}
std::ostream& operator<<(std::ostream& out, const Bibliography &b1)
{
for (Medium &Medium : b1.v)
{
out << Medium.toString() << std::endl;
}
return out;
}
You should not use reference_wrapper in vector, because vector is restricted when using it with classes that do not have a default constructor. reference_wrapper doesn't have it, look at these constructors of reference_wrapper:
// initialization (1)
reference_wrapper (type& ref) noexcept;
reference_wrapper (type&&) = delete;
// copy (2)
reference_wrapper (const reference_wrapper& x) noexcept;
In this line
v.resize(m_Size);
you want to create m_Size reference_wrapperobjects, but the default constructor for reference_wrapper doesn't exist, and code cannot be compiled.
You can use reference_wrapper with vector but you will get a compilation error
when a method of vector is called, that needs the default constructor to be defined.

cannot instantiate abstract class error [duplicate]

This question already has answers here:
Adding Elements to std::vector of an abstract class
(4 answers)
Closed 5 years ago.
I have a problem with my code.
I have three classes, and one of them is a pure abstract class. I don't know why I receive the error:
'note' cannot instantiate abstact class.
It may be because of STL usage, or I have made a mistake and I dont see it.
The problem is I tried without STL and it works, and I don't know what is the problem here because I think it it correct.
#pragma once
class note
{
protected:
int ziua;
int ora;
public:
note();
note(int day,int hour);
virtual void print()=0;
virtual ~note();
};
#include "note.h"
note::note()
{
}
note::note(int day, int hour) :ziua(day), ora(hour)
{
}
note::~note()
{
}
#pragma once
#include "note.h"
#include <iostream>
class apeluri:public note
{
char *numar_telefon;
public:
apeluri();
apeluri(int day, int h, char*phone);
void print()
{
printf("%d %d %s", ziua, ora, numar_telefon);
}
~apeluri();
};
#pragma once
#include <iostream>
#include "apeluri.h"
#include <vector>
#include "note.h"
using namespace std;
class remainder
{
vector<note> t;
public:
remainder();
void addsedinta(int zi, int ora, int durata, char*subi);
void addapel(int zi, int ora, char*phon)
{
apeluri *f;
f = new apeluri(zi, ora, phon);
t.push_back(*f);
}
void show()
{
}
~remainder();
};
In your remainder class, using vector<note> is illegal. note is abstract, so the vector can't create note objects.
Even if note were not abstract, your code would still not work correctly, because it would be affected by object slicing.
To store derived objects in a container of base classes, you must use pointers instead, ie vector<note*>:
#pragma once
#include <iostream>
#include <vector>
#include "note.h"
#include "apeluri.h"
using namespace std;
class remainder
{
private:
vector<note*> t;
remainder(const remainder &) {}
remainder& operator=(const remainder &) { return *this; }
public:
remainder();
~remainder()
{
for(std::vector<note*>::iterator i = t.begin(); i != t.end(); ++i) {
delete *i;
}
}
void addsedinta(int zi, int ora, int durata, char*subi);
void addapel(int zi, int ora, char*phon)
{
apeluri *f = new apeluri(zi, ora, phon);
t.push_back(f);
}
void show()
{
}
};
If you are using C++11 or later, this would be better written as this instead:
#pragma once
#include <iostream>
#include <vector>
#include <memory>
#include "note.h"
#include "apeluri.h"
using namespace std;
class remainder
{
private:
vector<unique_ptr<note>> t;
public:
remainder();
remainder(const remainder &) = delete;
remainder& operator=(const remainder &) = delete;
void addsedinta(int zi, int ora, int durata, char*subi);
void addapel(int zi, int ora, char*phon)
{
t.push_back(std::unique_ptr<apeluri>(new apeluri(zi, ora, phon)));
// in C++14 and later, use this instead:
// t.push_back(std::make_unique<apeluri>(zi, ora, phon));
}
void show()
{
}
};

Constructor of a children class that have an array that contains objects of another class

Dialog.h
#include "WBasic.h"
#include "WButton.h"
#include "WData.h"
#ifndef WDIALOG_H_INCLUDED
#define WDIALOG_H_INCLUDED
class WDialog : public WBasic
{
private:
WButton wB;
WData wD;
public:
//Constructor
WDialog(const int& e = 0, const WButton& = WButton(0,0), const WData& = WData(0,0,0));
~WDialog();
};
#endif // WDIALOG_H_INCLUDED
Dialog.cpp
#include <iostream>
#include "WDialog.h"
WDialog::WDialog(const int& e, const WButton& WBUTTON, const WData& WDATA) :
WBasic(e), wB(WBUTTON), wD(WDATA)
{
}
The code above works great, however I'm trying to make "WButton wB" a vector changing it to"WButton wB[3];"
class WDialog : public WBasic
{
private:
WButton wB[3];
WData wD;
};
But then I've no idea how deal with the Constructor.
You can use vector to solve this problem.
I have written a small example below.
#include <iostream>
#include <vector>
using namespace std;
class A{
};
class B{
public:
B():vec (4,A())
{
}
private :
vector<A> vec;
};
int main() {
// your code goes here
B obj();
return 0;
}
You can observe how I have initialized vector vec with three class A object.
In my opinion if you can (your compiler support C++11) prefer std::array
#include <array>
std::array<WButton, 3> wB;
Then in your contructor use an initializer list:
WBasic(e),
wB{WButton(...), WButton(...), WButton(...)},
wD(WDATA)

How to forward declare a class which is in a namespace

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