Collect data from an object of some other class





4.00/5 (1 vote)
There are circumstances, such as report or log entry, where we need to collect data from an object of some other (related or not) class. The C++ language only requires that we instruct the compiler how we intend to do it. This is simply achieved by defining a constructor of recipient_class...
There are circumstances, such as report or log entry, where we need to collect data from an object of some other (related or not) class.
The C++ language only requires that we instruct the compiler how we intend to do it.
This is simply achieved by defining a constructor of
recipient_class
from const source_class&
. We can then use the operator =()
(or the constructor) to copy the relevant data into an object that we can print, save or whatever.
class A { //... }; class B { B(const A& a) { //... } // ... }; // ... A a; // update a // ... B b = a; // get a data to bActually we can even change the data type in this process: this minimal console application gets a
double
from a A
and sets it's string representation in a B
.
Paste it into a VC console application project, compile and run.
#include <iostream> #include <sstream> struct A { int i; double d; // ... }; struct B { B(const A& a) : i(a.i) { std::wostringstream oss; oss << a.d; s = oss.str(); // ... } int i; std::wstring s; // ... }; int main(int, wchar_t*) { A a = {100, 1.2345}; B b = a; // the compiler will use b(a) to achieve it std::wcout << b.i << L'\t' << b.s << std::endl; // visualize the result return 0; }With the power of C++ (and the help of some analysis) we should not have to write several thousands such constructors. For instance, change the B constructor to:
template <class T> B(const T& t) : i(t.i) { std::wostringstream oss; oss << t.d; s = oss.str(); }Now
B::operator =()
operates on objects of any class presenting a i
named member convertible to a int
and a d
named member accepted by std::basic_ostream::operator <<()
.
With the added power of the Standard C++ Library (and again the help of some analysis) we can also handle all types and sizes of (for instance) int collections:
#include <vector> struct BB : B { template<class T> BB(const T& t) : BB::B(t), ai(t.ai.begin(), t.ai.end()) {} std::vector<int> ai; };A
BB
is a B
with an added std::vector<int> ai
member.
It is constructible from any class presenting the previous traits and a member standard container of objects convertible to int named ai
, for instance from:
#include <array> template <size_t t_s> struct AA : A { std::array<int, t_s> ai; AA(const A& a) : A(a) { for (int i = 0; i < t_s; ++i) ai[i] = i; } // ... };The main() demo becomes then:
int main(int, wchar_t*) { A a = {100, 1.2345}; B b = a; std::wcout << b.i << L'\t' << b.s << std::endl; // same as earlier AA<8> aa = a; // a AA having the values of previous A plus an array of eight int BB bb = aa; // Collect the aa data into bb std::wcout << bb.i << L'\t' << bb.s; for (size_t i = 0; i < bb.ai.size(); ++i) std::wcout << L'\t' << bb.ai[i]; std::wcout << std::endl; return 0; }Definitely no need of the complex constructs that you can find elsewhere (including CodeProject) :) cheers, AR