I want to make a class/struct where one of the attributes is functionally dependent on other attributes. How can this be achieved?
struct Numbers {
int a;
int b;
int c; // c == a+b
}
Numbers n1 {1, 2, 3}; // Ok.
Numbers n2 {1, 2, 4}; // Error!
In my use case, a, b, c are constant, if that matters (so const int may be used).
All attributes will appear many times in class/struct methods, so the goal is to cache the value a+b. Addition is used as an example, the dependency function may be more complex.
If a and b are mutable then you can't enforce that c is kept in sync; all three would have to be const for you to enforce this invariant.
The simplest approach would be to make c a function:
struct Numbers {
int a;
int b;
int c() const { return a + b; }
}
If you want the value of c to be cached instead of computed when needed then you need to hide a and b behind accessors as well so that you can update c when they are updated.
class Numbers {
public:
Numbers(int a, int b) : ma{a}, mb{b} { updateC(); }
int a() const { return ma; }
int b() const { return mb; }
int c() const { return mc; }
void a(int v) { ma = v; updateC(); }
void b(int v) { mb = v; updateC(); }
// No setter for c
private:
void updateC() { mc = ma + mb; }
int ma;
int mb;
int mc;
};
You can do something like that:
struct Numbers {
Numbers(int a, int b) : a(a), b(b), c(a + b) {}
private:
int a;
int b;
int c; // c == a+b
};
Edit:
To keep the values of a and b updated, and to get the values of those variables, you'll have to use get & set methods, like in #cdhowie response.
Related
You can redefine operator << in class by overload it.
However, how do you code it so that it would operates specific to a certain class member?
for example
class C
{
int a;
double b;
}
// I would like something like
void main ()
{
C c;
c.a << 1; // sets class member a to value 1;
}
I want a operator defined in Class C that operates specifically to class member a.
a pesudo-code would be
class C
{
int a;
double b;
void operator << (istream & fin)
{
... fin.get()... some code
}
}
Stating the obvious for a moment, assuming the variable is public, you'd use:
class C
{
int a;
double b;
}
// I would like something like
void main ()
{
C c;
c.a = 1; // sets class member a to value 1;
}
The << and >> operators are bit shifts, which have their own meaning. Overloading those for your own purpose is probably a bad idea.
The C++ way of doing things is to avoid setting member variables externally where possible (e.g. using RAII approaches, to set data at initialisation)....
class C
{
public:
C(int a, double b) : a(a), b(b) {}
int getA() const { return a; }
double getB() const { return b; }
private:
int a;
double b;
};
.... Or by adding a setter method if you really need it, e.g.
class C
{
public:
C(int a, double b) : a(a), b(b) {}
int getA() const { return a; }
double getB() const { return b; }
void setA(int v) { a = v; }
void setB(double v) { b = v; }
private:
int a;
double b;
};
You could in theory generate a new type, and overload the operators for that type, but it's not something I'd recommend (because changing the meaning of an operator is almost always a bad idea)
struct MyIntType {
int i;
// overload cast operator
operator int () {
return i;
}
// assign
MyIntType& operator = (const int& v) {
i = v;
return *this;
}
// not recommended :(
MyIntType& operator << (const int& v) {
i = v;
return *this;
}
};
class C
{
public:
MyIntType a;
double b;
};
void main ()
{
C c;
c.a << 1;
}
Having read your comment above, it sounds like you want to do this:
class C
{
public:
// I'm still not recommending this :(
C& operator << (const int& v) {
a = v;
return *this;
}
private:
int a;
double b;
};
void main ()
{
C c;
c << 1; //< now sets c.a
}
Here I need to add two numbers, but my constructor has only one parameter. And it should be has one parameter. Using the addFunc I need to add my two different numbers.
int result = 0;
class Num{
private:
int a;
public:
Num(int a) {
a = a;
}
int getA(){
return a;
}
void setA(int a){
a = a;
}
int addFunc() {
return result += getA();
}
}
};
Here is my 'main' function and I need to output the sum of two numbers which is supposed to be saves to 'result' variable.
The problem is that instead of getting the real result 5+6=11 I get this ->
Expanding on Bob__'s suggestion it seems likely that your code is supposed to look something a bit like this
class Num {
private:
int a;
public:
Num(int a) {
this->a = a;
}
int getA() {
return a;
}
void setA(int a) {
this->a = a;
}
int addFunc(Num other) {
return a + other.a;
}
};
int main()
{
Num num(5);
Num num2(6);
cout << num.addFunc(num2);
}
As you can see, it's a bit more logical, a bit simpler, and doesn't need to use a global variable to add two numbers togther.
When you write a constructor, you have the opportunity to test the values of the arguments from out of range or other unwanted situations in its body.
class a
{
int b;
public:
a(int c)
{
if(c < MIN_ALLOWED || c > MAX_ALLOWED)
{
// Take some measure
}
else
{
b = c;
}
}
};
But when you're dealing with const members, they should be initialized by means of an initializer list, so, in this case, how to prevent unwanted values?
class a
{
const int b;
public:
a(int c) : b(c)
{
// How to control "c" value?!...
}
};
Make a function:
class a {
int const b;
public:
a(int const c)
: b { initializeB(c) }
{
}
private:
static int initializeB(int const c)
{
if (c < MIN_ALLOWED || c > MAX_ALLOWED) {
// Take some mesure
return -1; // example
}
return c;
}
};
class a
{
const int b;
public:
a(int c) : b((c < MIN_ALLOWED || c > MAX_ALLOWED) ? throw std::logic_error("bad") : c)
{
// How to control "c" value?!...
}
};
You can delegate the verification and modification of the variable to a function.
class a {
public:
a(int c) : b(ValidateAndTransformInputParameter(c)) {}
private:
const int b;
int ValidateAndTransformInputParameter(int d) const {
if (d < 100) {
d = 100;
}
return d;
}
};
There are three major ways:
Chain the validation with the comma-operator:
a(int c) : b(validate(c), c) {}
Remember that the initializers are executed strictly depth-first, in declaration order, ignoring virtual inheritance.
Using the ternary operator:
a(int c) : b(validate(c) ? c : throw 0) {}
This needs the least amount of folderol if it's really a one-off.
Using a transforming and validating class or function:
a(int c) : b(process(c)) {}
Optionally, they might be combined with ctor-chaining, especially if more than one result comes from processing the inputs:
private:
struct process {
...
};
a(process x) : b(x.b), c(x.c), d(x.d) {}
public:
a(int c) : a(process(c)) {}
All of the above answers are good and work... but lest we forget, you can also do:
class a
{
public:
a(int c) : b([=]() -> int {
if (c < MIN_ALLOWED || c > MAX_ALLOWED)
throw std::logic_error("b");
return c;
}()) {}
private:
int b;
};
It looks awful in my opinion though, having a lambda in an initializer list, but it's still possible.
I have a class which has a member attribute consisting of an object defined elsewhere. In the code below, A contains a public attribute var which is a B:
class B {
public:
int x, y;
std::vector<int> z;
B(int a, int b, std::vector<int> c) {
x = a; y = b; z = c;
}
};
class A {
public:
B var;
A(int i, int j) {
std::vector<int> someVector;
B(i, j, someVector);
}
};
int main() {
A foo(5, 3);
return 0;
}
This (obviously) doesn't compile as var is instantiated upon an instantiation of A, too late for it to be constructed.
The best way I can do something similar is modify some code:
class B {
public:
int x, y;
std::vector<int> z;
B() {}
void setAttributes(int a, int b, std::vector<int> c) {
x = a; y = b; z = c;
}
};
class A {
public:
B var;
A(int i, int j) {
std::vector<int> someVector;
B.setAttributes(i, j, someVector);
}
};
This does compile because attributes are set after instantiation.
But is there a way to remain closer to the first code snippet?
A(int i, int j) : var(i, j, {}) {}
Also, in your code B(i, j, someVector); does not initialize member variable var, and B.setAttributes(i, j, someVector); wouldn't compile at all.
if you cannot define a useful default constructor and don't want the ugly two step initialization, I guess there is no way around a pointer to B. Something like
#include <memory>
class B {
public:
int x, y;
std::vector<int> z;
B(int a, int b, std::vector<int> c) {
x = a; y = b; z = c;
}
};
class A {
public:
std::unique_ptr<B> var;
A() {
std::vector<int> someVector;
var = std::make_unique<B>(5, 2, someVector);
}
};
int main() {
A foo();
return 0;
}
should do the trick.
I have this C++ class that one big complicated method compute that I would like to feed with a "compute kernel", a method of the same class. I figure I would do something along the lines of
class test {
int classVar_ = 42;
int compute_add(int a, int b)
{
compute(int a, int b, this->add_())
}
int compute_mult(int a, int b)
{
compute(int a, int b, this->mult_())
}
int compute_(int a, int b, "pass in add or multiply as f()")
{
int c=0;
// Some complex loops {
c += f(a,b)
// }
return c;
}
int add_(int a, int b){a+b+classVar_;}
int multiply_(int a, int b){a*b+classVar_;}
...
}
but I'm not sure how I would pass in add or multiply.
An alternative to this approach would be to pass in an ENUM of some sort to specify add() or multiply(), but I wanted to avoid a switch or if inside the loops.
What's best practice here?
As you suspected, passing a member function pointer is acceptable practice.
If you need to know the syntax, it is:
int compute_(int a, int b, int (test::*f)(int,int))
{
int c=0;
// Some complex loops {
c += (this->*f)(a,b)
// }
return c;
}
Representing member functions using integers, and switching, introduces programmer overhead to keep things up to date when the list of available operations changes. So you don't want that unless there's some important reason in a particular case.
One alternative is to make compute even more general -- instead of taking a member function, write a function template that takes any callable type:
template <typename BinaryFunction>
int compute_(int a, int b, BinaryFunction f) {
// body as before but `f(a,b)` instead of `(this->*f)(a,b)`
}
This more general template is great if someone wants to use it with some operator of their own invention, that isn't a member function of test. It's more difficult to use in the case of the member function, though, because someone needs to capture this. There are a few ways to do that -- a C++11 lambda, boost::bind, or writing out a functor longhand. For example:
template <typename BinaryFunction>
int compute_(int a, int b, BinaryFunction f) {
// body as before with `f(a,b)`
}
int compute_(int a, int b, int (test::*f)(int,int))
{
return compute_(a, b, bind_this(f, this));
}
Defining bind_this is a bit of a pain: it's like std::bind1st except that we'd like to work with a 3-arg functor whereas bind1st only takes a binary functor. boost::bind, and std::bind in C++11, are more flexible, and will handle the extra arguments. The following will do for this case, but doesn't work in general to bind 2-arg member functions:
struct bind_this {
int (test::*f)(int,int);
test *t;
int operator(int a, int b) const {
return (t->*f)(a,b);
}
bind_this(int (test::*f)(int,int), test *t) : f(f), t(t) {}
};
In C++11 you can just use a lambda:
int compute_(int a, int b, int (test::*f)(int,int))
{
return compute_(a, b, [=](int c, int d){ return (this->*f)(c,d) });
}
Use pointers to functions.
int compute(int a, int b, int (test::*f) (int, int) )
{
int c=0;
// Some complex loops {
c += (this->*f)(a,b)
// }
return c;
}
You have two alternatives :
using pointer to member function
using lambda functions
Example using pointer to member function :
#include <iostream>
class D
{
public:
D(int v ) : classVar_(v){}
int add_(int a, int b){return (a+b+classVar_);}
int multiply_(int a, int b){return (a*b+classVar_);}
private:
int classVar_;
};
class test {
public:
int compute_(int a, int b, D &d, int (D::*f)(int a, int b))
{
int c=0;
// Some complex loops {
c += (d.*f)(a,b);
// }
return c;
}
};
int main()
{
test test;
D d(1);
std::cout<<"add : " << test.compute_( 5, 4, d, &D::add_ ) << std::endl;
std::cout<<"add : " << test.compute_( 5, 4, d, &D::multiply_ ) << std::endl;
}
Example using lambda :
#include <iostream>
#include <functional>
class D
{
public:
D(int v ) : classVar_(v){}
int add_(int a, int b){return (a+b+classVar_);}
int multiply_(int a, int b){return (a*b+classVar_);}
private:
int classVar_;
};
class test {
public:
int compute_(int a, int b, std::function< int(int,int) > f)
{
int c=0;
// Some complex loops {
c += f(a,b);
// }
return c;
}
};
int main()
{
test test;
D d(1);
std::cout<<"add : " << test.compute_( 5, 4, [&d](int a, int b){ return d.add_(a,b); } ) << std::endl;
std::cout<<"add : " << test.compute_( 5, 4, [&d](int a, int b){ return d.multiply_(a,b); } ) << std::endl;
}