I have the following sample code and I wanted to know the correct way to get access to the Pass method in the CBar class. Currently I have found 3 ways to get access to this method and they are as follows:
Casting the object, ((CBar *) &foo)->Pass(1, 2, 3);
Using this syntax, foo.CBar::Pass(1,2,3);
Use the "using" syntax in the CFoo class declaration, using CBar::Pass.
The following is an example of a simple project to test this capability.
Foo.h
#include "bar.h"
class CFoo :
public CBar
{
private:
double m_a;
double m_b;
public:
CFoo(void);
~CFoo(void);
void Pass(double a, double b);
};
Foo.cpp
#include "Foo.h"
CFoo::CFoo(void)
{
m_a = 0.0;
m_b = 0.0;
}
CFoo::~CFoo(void)
{
}
void CFoo::Pass(double a, double b)
{
m_a = a;
m_b = b;
}
Bar.h
class CBar
{
int m_x;
int m_y;
int m_z;
public:
CBar(void);
~CBar(void);
void Pass(int x, int y, int z);
};
Bar.cpp
#include "Bar.h"
CBar::CBar(void)
{
m_x = 0;
m_y = 0;
m_z = 0;
}
CBar::~CBar(void)
{
}
void CBar::Pass(int x, int y, int z)
{
m_x = x;
m_y = y;
m_z = z;
}
And my main class DoStuff.cpp
#include "DoStuff.h"
#include "Foo.h"
CDoStuff::CDoStuff(void)
{
}
CDoStuff::~CDoStuff(void)
{
}
int main()
{
CFoo foo, foo1, foo2;
//This only gets to the Pass method in Foo.
foo.Pass(2.5, 3.5);
//Gets access to Pass method in Bar.
foo1.CBar::Pass(5,10,15);
//Can also case and access by location for the same result??
((CBar *) &foo2)->Pass(100,200,300);
return 0;
}
Are each of these options viable? Are some preferred? Are there pitfalls with using any one of the methods listed?
I am especially curious about the foo.CBar::Pass(1,2,3) syntax.
Thanks,
B
In this specific example all methods ultimately produce the same outcome.
In general case the outcomes might be different.
The "cast" method ((CBar *) &foo)->Pass(1, 2, 3); will preserve the dynamic nature of the call if Pass happens to be a virtual function. The cast can be performed in terms of reference type, BTW, ((CBar &) foo).Pass(1, 2, 3);. And using C++ style casts is a better idea in such situations.
The "qualified name" method foo.CBar::Pass(1,2,3); will suppress the dynamic nature of the call if Pass happens to be a virtual function, i.e. it is guaranteed to call CBar::Pass.
Related
#include <iostream>
using namespace std;
class Complex{
private:
int a,b;
public:
void set_data(int x,int y){
a=x,b=y;
}
void show_data(){
cout<<a<<" "<<b<<endl;
}
};
Complex add(Complex c, Complex d){
Complex temp;
int a = c.a+c.b;
int b = d.a+d.b;
temp.set_data(a,b);
return temp;
};
int main()
{
Complex c1,c2,c3;
c1.set_data(2,3);
c2.set_data(4,5);
c3 = add(c1,c2);
c3.show_data();
return 0;
}
want to know why add function is not wrking where as if i write c1.add(c2) and define function inside class then it works completely fine
"a" and "b" are declared as private. You cannot access it from outside the class. You need to make it public or provide getters or move it to inside the class.
As others pointed out, the member variables "a" and "b" are private and therefore can't be accessed from outside the class. Also, mind that your "add" function may not be mathematically correct. If you mean to add two complex numbers you probably want to write:
int a = c.a + d.a;
int b = c.b + d.b;
where I assume "a" is the real part and "b" the imaginary part
As the class variables "a" and "b" are private, you need to write getter functions for them. Sample code as follows:
#include <iostream>
using namespace std;
class Complex{
private:
int a,b;
public:
void set_data(int x,int y){
a=x,b=y;
}
void show_data(){
cout<<a<<" "<<b<<endl;
}
int getA(){
return a;
}
int getB(){
return b;
}
};
Complex add(Complex c, Complex d){
Complex temp;
int a = c.getA()+c.getB();
int b = d.getA()+d.getB();
temp.set_data(a,b);
return temp;
}
int main()
{
Complex c1,c2,c3;
c1.set_data(2,3);
c2.set_data(4,5);
c3 = add(c1,c2);
c3.show_data();
return 0;
}
Or make the variables public to directly access from anywhere. Sample as follows:
#include <iostream>
using namespace std;
class Complex{
public:
int a,b;
public:
void set_data(int x,int y){
a=x,b=y;
}
void show_data(){
cout<<a<<" "<<b<<endl;
}
};
Complex add(Complex c, Complex d){
Complex temp;
int a = c.a+c.b;
int b = d.a+d.b;
temp.set_data(a,b);
return temp;
};
int main()
{
Complex c1,c2,c3;
c1.set_data(2,3);
c2.set_data(4,5);
c3 = add(c1,c2);
c3.show_data();
return 0;
}
So, there's a lot to discuss here and it's a bit tough because it's hard to know what you're allowed to use. I've tried to remove that notion from my courses, at least.
Your class lacks any constructors. Relying solely on a setter is poor practice. Constructors are the correct way to initialize an object, and they are more efficient than a default initialization + setter.
You overuse the comma operator for no real gains. It just muddies readability.
Your add() function attempted to access private data, that's a big no-no. It would defeat the purpose if any free function could access private data as it pleased. The reason implementing the function inside the class worked fine is because as a class member function, it has access to the private section. Either make it a class member funtion OR add getters for your data.
The following sample adds constructors, replaces functions with operator overloads where they fit, and made a few other "better" practice changes. It also includes functionality that is available in C++17.
When I help with homework questions like this, my preference is to use a couple things that are likely to have not been discussed yet; it helps prevent copy/paste dishonesty. But I believe it still helps in seeing the logic play out.
#include <iostream>
#include <string>
#include <tuple>
class Complex {
public:
Complex() = default;
Complex(int r, int i) : m_real(r), m_imaginary(i) {}
auto get_data() const { return std::make_tuple(m_real, m_imaginary); }
void set_data(int x, int y) {
m_real = x;
m_imaginary = y;
}
private:
int m_real = 0;
int m_imaginary = 0;
};
Complex operator+(const Complex& lhs, const Complex& rhs) {
auto [leftReal, leftImaginary] = lhs.get_data(); // C++17 feature
auto [rightReal, rightImaginary] = rhs.get_data();
return Complex(leftReal + rightReal, leftImaginary + rightImaginary);
}
// No newline printed here because no other Standard type does that
std::ostream& operator<<(std::ostream& sout, const Complex& obj) {
auto [real, imaginary] = obj.get_data();
// If you care about setw() interacting with your output, this intermediate
// step matters
std::string val =
std::to_string(real) + " + " + std::to_string(imaginary) + "i";
return sout << val;
}
int main() {
Complex c1(2, 3);
Complex c2(4, 5);
Complex c3 = c1 + c2;
std::cout << c3 << '\n';
return 0;
}
I'm having a problem of storing data into the private array in a class.
I tried to Google and didn't find any solution.
Here's my code:
Foo.h
class Foo {
private:
int arr[10];
double d;
public:
Foo::Foo(double d) {
this->d = d;
}
// ...
};
Foo.cpp
int main() {
double d = 123.456;
int array[10];
// Getting data from user input by for-loop 10 times.
Foo f = Foo(d);
And here's my problem -- how to save the array into the f?
Seems like using pointer (*f.arr = array;) doesn't acturally change the arr.
I tried this solution by adding
class Foo {
// ...
Public:
Foo::Foo(int arr_, double d_) : arr_(new int[10]), d_(d) { };
But the Visual Studio 2017 says the array is not initialized.
I also tried this solution, but VS says cannot modify the array in this scope.
Please help. Thank you in advance.
#include <algorithm> // std::copy()
#include <iterator> // std::size()
class Foo {
private:
int arr[10];
double d;
public:
Foo(double d, int *data)
: d{ d }
{
std::copy(data, data + std::size(arr), arr);
}
// ...
};
Suppose I have a bunch of inherited classes like this:
...and they all serve the purpose of making all sorts of polynomials. Class X is mainly a variable tank, classes A, B, etc are all virtual public X and each creates ont type of polynomial, class Y makes the calls. Besides A and B, any other class can be added.
Now, everything works but for a newly added "virtual public" class I need to reuse some member function(s) from other classes, here from A inside class B. I tried to make the simplest example:
#include <iostream>
#include <cmath>
#include <functional>
// variable tank
class X
{
protected:
// general variables
double *m_c;
int m_n;
double m_w;
// funcX related
double m_r;
int m_i {0};
public:
~X() = default;
/* Simple bracketed root-finding. This is called from more than
* one "virtual public" classes.
*/
const double funcX(const double &x, const double &y, \
std::function<const double(const double&, const int&)> fp, \
const int &k)
{
double a {x}, b {y}, fmid;
while (m_i<100)
{
m_r = 0.5*(a + b);
fmid = fp(m_r, k);
if (fabs(b-a) <= 1e-3)
break;
if (fmid < 0)
b = m_r;
else
a = m_r;
++m_i;
}
return m_r;
}
};
// one of the many classes that generate polynomials
class A: virtual public X
{
public:
void funcA(const int &n)
{
// set order
m_n = n;
// calculate X::m_c[i]
m_c = new double[m_n+1];
for (short i=0; i<=m_n>>1; ++i)
{
int sgn {i%2 ? -1 : 1};
m_c[i<<1] = sgn/((i + 1.0)*(i + 1.0));
}
// The polynomial is zero somewhere, use funcX() to find where.
m_w = funcX(5.0, 0.0, \
[this](const double &x, const int &n) \
{ return calcA(x, n); }, \
m_n);
}
// calculates the value of the polynomial of order n, at x
const double calcA(const double &x, const int &n) const
{
double out {static_cast<double>(m_c[0])};
for (short i=1; i<=n; ++i)
out = m_c[i] + x*out;
return out;
}
};
class B: virtual public X
{
private:
A m_a; // otherwise the lambda function does not "catch" it
public:
void funcB(const int &n)
{
// same as in A
m_n = n;
// same as in A, calculate coefficients
m_c = new double[m_n+1];
for (short i=0; i<=m_n; ++i)
{
int sgn {i%2 ? -1 : 1};
m_c[i] = sgn/((i + 1)<<1);
}
/* Here I need A::calcA(). Instead of duplicating the code,
* I want to call it through X::funcX(). The code compiles,
* but it crashes.
*/
m_w = funcX(0.5, 1.0, \
[this](const double &x, const int &n) \
{ return m_a.calcA(x, n); }, \
m_n);
}
const double getW() const { return m_w; }
};
class Y: public A, public B
{
public:
Y(const int &n, const int &i)
{
// call one of the "virtual public" classes through i
switch (i)
{
case 1: funcA(n); break;
case 2: funcB(n); break;
}
}
void printC() { for (short i=0; i<=m_n; ++i) std::cout << m_c[i] << '\n'; }
void printW() { std::cout << m_w << '\n'; }
void printA(const double &x, const double &n) { std::cout << A::calcA(x, n) << '\n'; }
};
int main(int argc, char *argv[])
{
int N {6};
Y *y;
for (short i=1; i<=2; ++i)
{
y = new Y(N, i);
y->printC();
y->printW();
y->printA(1.2, N);
}
return 0;
}
class X:
X::funcX() is a simple root-finding algorithm which gets called in more than one virtual public classes (A, B, etc). m_c, m_n, m_w are shared variables.
classes A and B:
their main function is funcA() (and funcB(), and so on) and it creates the polynomial (in the body, there's a for loop), based on the calculated order, X::m_n. Evaluating the polynomial is A::calcA(). This needs to be either called by class B, too, or redefined. I'd rather avoid the latter because of the code bloating. It also doesn't look very "professional" for my fairly beginner level...
class Y
This calls any of the virtual public classes based on argument i (the switch/case).
The code compiles, but crashes. It prints the case for. This example points to A::funcA() as the culprit, but in the original program I can see that the coeficients, m_c[i], are not even initialized with dynamic memory, as in trying to print out m_c[0] crashes. I tried moving the new double[] insode the function in A, but that doesn't work.
I don't know how to make it. Does this make sense, is it possible? If yes, how?
Edit: Forgot to add that I can't just move calcA() from A to the top, in X, because each polynomial is evaluated differently, as in there are shortcuts, changes, in every one that makes it possible to have different, optimized evaluations for each polynomial. I could make X::calcA() a universal one, but there will be a performance penalty, which I'd rather not pay.
It seems that your problem is induced by problems with design. When you need to use methods from other class that may mean:
The is a problem with "single responsibility" principle. Class does too much. For example numerical equation solving algorithms are self-sufficient entities and shouldn't be part of polynomial. They can work with any polynomial.
There is a problem with inheritance tree. For example a common ancestor should be created and that common methods should be in it. Note, that if you can't find short and understandable name for that ancestor, then this is not the solution.
Inheritance is not used properly. For example I can't see virtual methods in your code which is strange.
Let's get closer to your example. You are using virtual multiple inheritance which is considered to be very heavy pattern and usually should not be used. Moreover, there are no virtual methods in your code, so you actually do not use inheritance at all. You either must drop inheritance, or think of common methods which make sense for all your classes. For functions this seems to be an ability to calculate function value in specified point. Then move all code, that is not describing polynomials or functions out of the classes. Move out numerical solvers. This will allow to reuse them for all your classes, that support needed interface. Get rid of Y class at all. It seems, that it is needed to emulate virtual methods with switches and enums. You don't need it, rename funcA and funcB just to func if they are semantically the same and do the same thing for different types of polynomials.
I have a C++ class with two constructors (a default one and another with arguments). In order to reuse code, I avoided initializing class members at the constructor level, and I'm doing it in an Initialize method instead, which I am calling from both constructors. This way, I was hopping to minimize code lines and repeated code:
Location::Location(){
double pos[POSITION_SIZE] = {0};
this->Initialize(const_cast<char*>(""), const_cast<char*>(""), pos);
}
Location::Location(char *id, char *code, double pos[POSITION_SIZE]){
this->Initialize(id, code, pos);
}
void Location::Initialize(char *id, char *code, double pos[POSITION_SIZE]){
strcpy(this->ID, id);
strcpy(this->code, code);
this->position[0] = pos[0];
this->position[1] = pos[1];
this->position[2] = pos[2];
this->attribute1 = 0;
this->attribute2 = 0;
}
header:
class Location{
public:
Location();
Location(char *id, char *code, double pos[POSITION_SIZE]);
private:
// This method initializes the location attributes given as parameters
void Initialize(char *id, char *code, double pos[POSITION_SIZE]);
// Name/identifier of the location
char ID[ID_LENGTH];
// FIR identifier
char code[ID_LENGTH];
// Location's coordinates (lat, lon, alt)
double position[POSITION_SIZE];
// Attribute 1
double attribute1;
// Attribute 2
double attribute2;
};
I know that using initialize methods is a bad praxis when used because old school coding style or avoiding the usage of exceptions at constructor for example. But my goal here was reducing code, so unless some guru of stackoverflow says the opposite, I think it is not wrong (but I'm here to learn, so please destroy all my convictions).
The problem is that I'm getting a warning for not initializing class members within the cosntructor. The compiler doesn't like them to get initialized at the Initialize method. So, any way of making the compiler happy? Should I forget aboput Initialize method usage?
I would use constructor delegation, something like:
#include <iostream>
using namespace std;
class foo
{
public:
foo()
: foo(1, "2", 3.) // delegate to the other constructor with defaults...
{ }
foo(int a, std::string b, double c)
: _a(a), _b(b), _c(c)
{ }
private:
int _a;
std::string _b;
double _c;
};
int main() {
foo f1{};
foo f2{1, "3", 4.};
return 0;
}
With the caveat that you can use atleast c++11...
This is probably a really basic error I'm making, but I'm quite new to c++ so please don't judge!
Basically, I've got two classes as follows:
class A{
private:
vector< vector<int> > images;
public:
int f1(int X, int Y);
}
class B{
private:
int x;
int y;
public:
int f2(A var);
}
I want to be able to call B.f2(A) with defined variables A and B and have f2() call A.f1(x,y). So far, all this works.
But the function f1 assigns values to the vector 'images' which aren't there when f2() returns. Any ideas why?
Here's the code:
int A::f1(int X, int Y){
// Some stuff to resize images accordingly
images[X][Y] = 4;
return 0;
}
int B::f2(A var){
var.f1(x, y);
return 0;
}
int main(){
A var1;
B var2;
// Stuff to set var2.x, var2.y
var2.f2(var1);
// HERE: var1.images IS UNCHANGED?
}
this is because you have passed A by value. instead, pass it by reference.
void fn(A& p);
^ << refer to the original object passed as the parameter.
as it is now, your program creates, and then mutates a copy of var1.
when you do not want to mutate the parameter, you can pass it as a const reference:
void fn(const A& p);
^^^^^ ^