I'm a beginner in C++ so I'm not sure how to make the question more detail. I'm sorry.
So my professor gave me this header file and told me to write the function definition:
class Move
{ private:
double x;
double y;
public:
Move( double a = 0, double b = 0 ); // sets x_, y_ to a, b
void showmove(Move number) const; // shows current x_, y_ values
// add : Move --> Move
// to add x_ of input object to x_ of invoking object to get new x_,
// to add y_ of input object to y_ of invoking object to get new y_,
// to create new object initialized to new values and return it
Move add( const Move &m ) const;
void reset( double a = 0, double b = 0 ); // resets x, y to a, b
};
I don't understand the function Move add( const Move &m ) const;. Usually an add function look like this int add( int a, int b) . So combine 2 inputs together to make 1 output. But the function Move add only has one input. I don't know how to write a definition for it. I asked my friends and we come up with something like A.add(B), but I'm not sure if it makes any sense.
Thank you for reading and sorry for my English
The definition should be
Move add(const Move& m) {
return Move(this->x+m.x, this->y+m.y);
}
It wants you to use m's attributes to get the results directly with only one parameter (reference to a Move object) instead of two (coordinates) .
Indeed, to invoke this method :
Move A/*sthg*/;
Move B/*sthg*/;
Move C = A.add(B);
Related
I am new to dart and am having issues storing data in a class. I know how to create instances but I then want to store each instance into a map that I can easily access. Here is my code below...
class myCar{
var myMapOfCars = new Map(); // I wanted this to be a class level variable that I can continuously add or remove from.
String carName; // Instance
myCar({this.carName});
addInfoToMap() {
// Some logic to increment the index or create the index the
myMapOfCars[theKey] = this.carName; // This should be the class variable.
}
}
Every time I call "addInfoToMap", the "myMapOfCars" instance is reinitialized and empty again. I wanted to add/append into the map so I can have as many cars in there as I want. I am open to other solutions as well, I come from Swift and I know you can do it in Swift. It just makes everything really clean.
Thanks for your help!!
The documentation "Class variables and methods" would be appropriate for this.
Static variables
Static variables (class variables) are useful for class-wide state and
constants:
class Queue {
static const initialCapacity = 16;
// ···
}
void main() {
assert(Queue.initialCapacity == 16);
}
Static variables aren’t initialized until they’re used.
Static methods
Static methods (class methods) don’t operate on an instance, and thus
don’t have access to this. They do, however, have access to static
variables. As the following example shows, you invoke static methods
directly on a class:
import 'dart:math';
class Point {
double x, y;
Point(this.x, this.y);
static double distanceBetween(Point a, Point b) {
var dx = a.x - b.x;
var dy = a.y - b.y;
return sqrt(dx * dx + dy * dy);
}
}
void main() {
var a = Point(2, 2);
var b = Point(4, 4);
var distance = Point.distanceBetween(a, b);
assert(2.8 < distance && distance < 2.9);
print(distance);
}
You can use static methods as compile-time constants. For example, you
can pass a static method as a parameter to a constant constructor.
As an additional reference, you can also visit this blog.
class X extends Y {
X(int a, int b) : super(a,b);
}
Can someone give me an explanation about the syntax meaning of the colon :?
This feature in Dart is called "initializer list".
It allows you to initialize fields of your class, make assertions and call the super constructor.
This means that it is not the same as the constructor body. As I said, you can only initialize variables and only access static members. You cannot call any (non-static) methods.
The benefit is that you can also initialize final variables, which you cannot do in the constructor body. You also have access to all parameters that are passed to the constructor, which you do not have when initializing the parameters directly in the parentheses.
Additionally, you can use class fields on the left-hand of an assignment with the same name as a parameter on the right-hand side that refers to a parameter. Dart will automatically use the class field on the left-hand side.
Here is an example:
class X {
final int number;
X(number) : number = number ?? 0;
}
The code above assigns the parameter named number to the final field this.number if it is non-null and otherwise it assigns 0. This means that the left-hand number of the assignment actually refers to this.number. Now, you can even make an assertion that will never fail (and is redundant because of that, but I want to explain how everything works together):
class X {
final int number;
X(number): number = number ?? 0, assert(number != null);
}
Learn more.
It's ok to access non static member in initializer list.
class Point {
num x, y;
Point(this.x, this.y);
Point.origin(): this.x = 10, this.y = 10;
}
main() {
Point p = Point.origin();
print(p.x); // 10
}
class test
{
char *str;
public:
test(char *p_str) /**default constructor**/
{
cout<<"Default\n";
int l = strlen(p_str) + 1;
str = (l ? new char[l] : 0);
memcpy(str,p_str,l);
}
test(const test& ob) /**copy**/
{
cout<<"Copy\n";
int l = strlen(ob.str) + 1;
str = (l ? new char[l] : 0);
memcpy(str,ob.str,l);
}
test(test&& ob) /**move constructor **/
{
cout<<"Move Constructor\n";
str = ob.str;
ob.str = nullptr;
}
void my_swap(test &ob1 , test &ob2) /**swap function**/
{
swap(ob1.str , ob2.str);
}
test& operator=(test ob) /**copy is called because of pass by value **/
{
cout<<"Copy Assignment operator\n";
my_swap(*this,ob);
return *this;
/**copy is destroyed as object passed by value is destroyed just after the function returns;**/
}
~test()
{
cout<<"Destructor\n";
delete[] str;
}
void print_str()
{
cout<<str<<"\n";
}
};
The above class contains simple implementation of rule of 5 in c++.Now when a vector of this class is created as following.
int main()
{
vector<test> vec1;
vec1.push_back(test("Hi!There"));
return 0;
}
I get the following output
Default
Move Constructor
Destructor
Destructor
And when one more object is pushed into the vector like this
int main()
{
vector<test> vec1;
vec1.push_back(test("Hi!There"));
vec1.push_back(test("Hello! There"));
return 0;
}
The output is
Default
Move Constructor
Destructor
Default
Move Constructor
Copy
Destructor
Destructor
Destructor
Destructor
Now my question is why is the copy constructor called in the second case and not the first.
Thanku
Since you have 5 destructor calls instead of 4 I assume that the vector had to reallocate it's internal storage when you tried to push the second item. This means that the vector had to move the first pushed item to the newly allocated (larger) memory area. However when a vector reallocates it storage and has to transfer items from the old memory block the the new one, it may happen that the item is transferred with copy instead of move. Reason: How to enforce move semantics when a vector grows?
In your case the correct solution would be using vec1.reserve(2) (before pushing items) to avoid the unnecessary reallocation even if the reallocation happens with move. Frequent reallocation is often the target of memory usage optimization.
I am currently working on building an ABM model using C++.
I have classes that have the need to interact with each other, because e.g. class B needs to examine values in class A and return some evaluation on it, which then class C might want to read. Classes need not to change other classes values, only to read from them.
Class B in my current implementation has a po
inter to a vector containing all members of Class A. The pointer is there for two order of reason: it makes easier to initialize the vector, and the vector is left in the scope of main so that I can access and loop over it, calling the members of class A for each agent.
My MCVE:
#include <iostream>
#include <vector>
using namespace std;
class A; // Forward declaration
class B{
int id,
some_value;
vector<A> * A_vec;
public:
// Overloaded constructor
B(int ID, vector<A> & PTR)
{
A_vec = & PTR;
id = ID;
some_value = 0;
};
// Copy Constructor
B( const B& that ):
id(that.id),
some_value(that.some_value)
{
// Pointer ??
};
// Non-default destructor -> uncomment leads to seg_fault
/*
~B(){ delete [] A_vec;};
*/
// Assignment operator
B& operator=(const B& that)
{
id = that.id;
some_value = that.some_value;
// Pointer ??
return *this;
};
//Methods to update different variables go here ..
void do_stuff();
};
class A{
B & class2_ref;
vector<double> o;
public:
int stuff;
// Overloaded constructor
A(int STUFF, B & REF, vector<double> O):
class2_ref(REF),
o(O)
{
stuff = STUFF;
};
// Methods to update different variables go here ..
};
void B::do_stuff()
{
int L = A_vec->size();
for(int l = 0; l<L; l++) some_value += (*A_vec)[l].stuff; // Perform some operation
};
int main(){
int I = 5; // Number of objects of A
vector<double> O(12,2); // Some numbers in here
B b(0,A_vec);
for(int i = 0; i< I; i++)
{
A a(i,b,O);
A_vec.push_back(a);
}
b.do_stuff();
cout<< "Debugging MCVE" << endl;
return 0;
}
My question then is:
Should I implement the destructor/copy constructor/assignment operator in class B? What about class A ? If so, can you please point me to the correct syntax(for the destructor the one above in comments leads to seg fault).
My understanding is that this might be one of the case in which I am happy with a "shallow" destruction of the pointer, because both class B and vector<A> will go out of scope at the return statement. class B owns the pointer, which gets destructed when it is due, and the same for vector.
But then, what about the other member from the rule of three?
There is only one object of class B planned, but I might (small chance) want to generalize later on.
if a class have a pointer type, you should implement a destructor, and i would suggest implementing a copy and an assignment operator as well, else you will be dealing with the same object from 2 different places, which could cause you some errors, for example -
void someFunction(B &b)
{
B a = b;
}
B b(0,A_vec);
someFunction(b); //After finishing someFunction, it will try to delete the vector from a , but it is the same vector you used in b.
b.do_stuff(); // Would cause a seg error
And for the destructor syntax, just delete the vector, not its content, it will use the vector default destrctor on the content:
delete A_vec
just make sure you dont use it if its not initialized, i would suggest just building a empty vector on each ctor of the class, that way you wont get a seg fault and you can use delete.
Update: clarification, more clear focus and shortened example:
Can I circumvent the M op+(M&&,M&&) overload? Assuming, I want good handling of RValues? I guess the other three overloads are required.
Reason why I have the (&&,&&) overload in the first place:
Normally I would not provide M op+(&&,&&), but I seem to need it: When providing overloads for (&&,&) and (&,&&) the compiler gets into an ambiguity. Is there a better way to resolve it then to add another implementation variant?
You can also look at the complete code.
struct Matrix {
...
// 2ary ops
friend Matrix operator+(const Matrix &a, Matrix &&b ) { b+=a; return move(b); }
friend Matrix operator+(Matrix &&a, const Matrix &b) { a+=b; return move(a); }
friend Matrix operator+(const Matrix &a, Matrix v) { v+=a; return v; }
friend Matrix operator+(Matrix &&a, Matrix &&b) { a+=b; return move(a); }
// ... same for operator*
// ... assume impl of operator+=,*= and move semantics
};
int main() {
Matrix a{2},b{3},c{4},d{5};
Matrix x = a*b + c*d; // reuires &&,&& overload
std::cout << x << std::endl;
}
The following helper function returns the first value if it an rvalue, otherwise the second value (which may be an rvalue, but may not be).
template <class T1, class T2>
typename std::enable_if<! std::is_reference<T1>::value, T1&&>::type
get_rvalue(T1&& t1, T2&& t2) { return std::forward<T1>(t1); }
template <class T1, class T2>
typename std::enable_if<std::is_reference<T1>::value, T2&&>::type
get_rvalue(T1&& t1, T2&& t2) { return std::forward<T2>(t2); }
The following helper function returns the other value not returned above.
template <class T1, class T2>
typename std::enable_if<! std::is_reference<T1>::value, T1&&>::type
get_non_rvalue(T1&& t1, T2&& t2) { return std::forward<T2>(t2); }
template <class T1, class T2>
typename std::enable_if<std::is_reference<T1>::value, T2&&>::type
get_non_rvalue(T1&& t1, T2&& t2) { return std::forward<T1>(t1); }
This just compares if two types are the same, ignoring references and const.
template <class T1, class T2>
struct is_same_decay : public std::is_same<
typename std::decay<T1>::type,
typename std::decay<T2>::type
> {};
Then we can do just one overload for each function (using templates) like the following:
// 2ary ops
template <class M1, class M2>
friend typename std::enable_if<
is_same_decay<M1, Matrix>::value &&
is_same_decay<M2, Matrix>::value,
Matrix>::type
operator+(M1&& a, M2&& b)
{
Matrix x = get_rvalue(std::forward<M1>(a), std::forward<M2>(b));
x += get_non_rvalue(std::forward<M1>(a), std::forward<M2>(b));
return x;
}
template <class M1, class M2>
friend typename std::enable_if<
is_same_decay<M1, Matrix>::value &&
is_same_decay<M2, Matrix>::value,
Matrix>::type
operator*(M1&& a, M2&& b)
{
Matrix x = get_rvalue(std::forward<M1>(a), std::forward<M1>(b));
x *= get_non_rvalue(std::forward<M1>(a), std::forward<M1>(b));
return x;
}
Note above, if either M1 or M2 is an rvalue, get_rvalue(a, b) will return an rvalue, hence in this case Matrix x will be populated by a move, not a copy. Named return value optimisation will probably ensure that there is no copy (or even move) required into the return value, as x will be constructed in the place of the return value.
Full code is here.
Matrix& operator=(Matrix&& o) { swap(*this,o); };
First, your Matrix class has nothing (as of yet) that needs moving, so you shouldn't bother writing one. Like a copy constructor, only define one if you need to. Let the compiler take care of it unless you have a legitimate need (like storing a naked pointer).
Second, that function of yours doesn't move; it swaps. An "idiomatic" swap-based move involves a temporary, like this:
Matrix temp;
swap(o, temp);
swap(temp, *this);
friend Matrix operator+(const Matrix &a, Matrix &&b ) { b+=a; return move(b); }
friend Matrix operator+(Matrix &&a, const Matrix &b) { a+=b; return move(a); }
friend Matrix operator+(const Matrix &a, Matrix v) { v+=a; return v; }
friend Matrix operator+(Matrix &&a, Matrix &&b) { a+=b; return move(a); }
What are you trying to accomplish here? Again, your object doesn't have anything that gets moved; there's no point in doing this. Just because you could move something, doesn't mean you should. If you really wanted to cut down on code duplication, you would do things normally:
friend Matrix operator+(const Matrix &a, const Matrix &b) { Matrix temp = a + b; return temp; }