This question already has answers here:
What is The Rule of Three?
(8 answers)
Closed 8 years ago.
I made a minimal example:
#include <iostream>
#include <conio.h>
using namespace std;
// skipped getters and setters and bounds checking for brevity
struct Vertex {
int x,y;
Vertex() {
}
Vertex(int x, int y) {
this->x = x;
this->y = y;
}
};
struct Polygon {
Vertex *vertexlist;
Polygon() {
}
Polygon(Vertex *v) {
vertexlist = new Vertex[4]; //hard coded 4 vertices for example brevity
for(int i=0;i<4;i++) {
vertexlist[i] = v[i];
}
}
Vertex& getVertex(int index) const {
return this->vertexlist[index];
}
};
struct PolyList {
Polygon *polylist;
int lastpoly;
PolyList() {
polylist = new Polygon[10]; //hard coded 10 for example brevity
lastpoly = 0;
}
void add(const Polygon& p) {
polylist[lastpoly++] = p;
}
};
ostream& operator<<(ostream& o, Vertex& v) {
return o << "(" << v.x << ", " << v.y << ")";
}
ostream& operator<<(ostream& o, const Polygon& p) {
for(int i=0;i<4;i++) {
o << p.getVertex(i) << ", ";
}
return o;
}
ostream& operator<<(ostream& o, PolyList& pl) {
for(int i=0;i<pl.lastpoly;i++) {
o << pl.polylist[i] << endl;
}
return o;
}
int someFunc() {
Vertex *vl = new Vertex[4];
PolyList pl;
vl[0] = Vertex(1,2);
vl[1] = Vertex(3,4);
vl[2] = Vertex(5,6);
vl[3] = Vertex(7,8);
pl.add(Polygon(vl)); // this Polygon goes out of scope after this line
cout << pl << endl;
}
int main() {
someFunc();
}
(So tl;dr, Polygon is a list of 4x Vertex, and PolyList is a list of Polygon:s. Polygon:s are add()ed to PolyList by instantiating a temporary Polygon)
Now, this leaks memory, because the Vertices in Polygon are never freed. However, if I add a destructor:
Polygon::~Polygon () {delete [] vertices}
then
cout << pl << endl;
will not work because the Polygon has gone out of scope and the destructor frees the vertices.
I could have the PolyList destructor call a Polygon->free() function. Alternatively, I could have the Polygon::Polygon(Vertex *v) deep copy all the vertices in v. Then PolyList::PolyList(Polygon &p) could deep copy p.
I could also make a PolyList::createPolygon(int x1, int y1, int x2, int y2...) but that flies in the face of OO.
What is the proper way to handle this kind of situation in C++? Never mind my actual example where a memory leak would not be a problem, I'm talking in principle. If I make an hierarchical object tree, I want to copy the pointers, not deep copy the objects.
EDIT: I'm trying to learn C++ on a deep level, so this is not about using vector<> or another "canned solution"; that is not what I'm after here, though I'm sure that is a good solution if the above example was an actual problem I was having. The example above is just the briefest example I could think of to explain my question.
You could use smart pointers and STL containers (mainly std::vector as suggested by PaulMcKenzie).
They will help a lot.
Your example using std::vector
#include <iostream>
#include <conio.h>
#include <vector>
using namespace std;
// skipped getters and setters and bounds checking for brevity
struct Vertex {
int x, y;
Vertex() {
}
Vertex(int x, int y) {
this->x = x;
this->y = y;
}
};
typedef vector<Vertex> vertex_list_t;
struct Polygon {
vertex_list_t vertexlist;
Polygon() {
}
Polygon(vertex_list_t v) {
//hard coded 4 vertices for example brevity
for (int i = 0; i<4; i++) {
vertexlist.push_back(Vertex(i, i));
}
}
Vertex getVertex(int index) const {
return vertexlist[index];
}
};
typedef vector<Polygon> polygon_list_t;
ostream& operator<<(ostream& o, Vertex& v) {
return o << "(" << v.x << ", " << v.y << ")";
}
ostream& operator<<(ostream& o, const Polygon& p) {
for (auto v: p.vertexlist) {
o << v << ", ";
}
return o;
}
ostream& operator<<(ostream& o, polygon_list_t& pl) {
for (auto &p : pl) {
o << p << endl;
}
return o;
}
int someFunc() {
vertex_list_t vl = {
Vertex(1, 2),
Vertex(3, 4),
Vertex(5, 6),
Vertex(7, 8)
};
polygon_list_t pl;
pl.push_back(Polygon(vl)); // this Polygon goes out of scope after this line
cout << pl << endl;
return 0;
}
int main() {
someFunc();
}
What's the real deal?
In the line
pl.add(Polygon(vl)); // this Polygon goes out of scope after this line
you pass the polygon as a temporary and:
$12.2/3- "Temporary objects are destroyed as the last step in evaluating the full-expression (1.9) that (lexically) contains the point where they were created. This is true even if that evaluation ends in throwing an exception."
change that line by:
Polygon p1(vl);
pl.add(p1); // this Polygon NOT goes out of scope after this line
You can use shared_ptrs as the solution. i.e.
#include "stdafx.h"
#include <iostream>
#include <conio.h>
#include <memory>
#include <list>
#include <vector>
using namespace std;
struct Vertex
{
int x,y;
Vertex() : x(0), y(0)
{
}
Vertex(int _x, int _y)
{
x = _x;
y = _y;
}
};
struct Polygon
{
vector<Vertex> vertexes;
Polygon()
{
}
Polygon(Vertex *v)
{
const int ELEMS_COUNT = 4;
vertexes.reserve(ELEMS_COUNT);
vertexes.insert(vertexes.end(), v, v + ELEMS_COUNT);
}
Vertex getVertex(int index) const
{
return vertexes[index];
}
};
typedef shared_ptr<Polygon> PolygonPtr;
struct PolyList
{
std::list<PolygonPtr> polylist;
void add(PolygonPtr p)
{
polylist.push_back(p);
}
};
ostream& operator<<(ostream& o, const Vertex& v) {
return o << "(" << v.x << ", " << v.y << ")";
}
ostream& operator<<(ostream& o, const Polygon& p) {
for (auto& p : p.vertexes)
{
o << p << ", ";
}
return o;
}
ostream& operator<<(ostream& o, PolyList& pl) {
for(auto& p : pl.polylist)
{
o << *p << endl;
}
return o;
}
int someFunc() {
Vertex vl[] = {Vertex(1, 2), Vertex(3, 4), Vertex(5, 6), Vertex(7, 8)};
PolyList pl;
pl.add(PolygonPtr(new Polygon(vl)));
cout << pl << endl;
return 0;
}
int main()
{
someFunc();
return 0;
}
Related
I'm using visual studio.
I have 3 class.
It's ok when I try to print Rectangle ABCD, but when i push ABCD into Array [rectangle] A and try to print ABCD again, the "wntdll.pdb not loaded" appear and i continue, it's "triggers breakpoint error!!" at delete in ~Rectangle()
I know it's something up to the pointer in class Rectangle but can't firgure out.
`int main(){
Array<Rectangle>A;
Rectangle a;
cout << a; //It's oke
A.PushBack(a); // problem here
cout<<a;
}`
class Point
{
private:
float _x;
float _y;
public:
float GetX() { return _x; }
float GetY() { return _y; }
public:
Point();
Point(float, float);
Point(const Point&);
~Point() {};
public:
string ToString() const;
public:
friend istream& operator>>(istream&, Point*);
friend ostream& operator<<(ostream&, const Point&);
};
Point::Point() {
_x = 1;
_y = 1;
}
Point::Point(float x, float y) {
_x = x;
_y = y;
}
Point::Point(const Point& a) {
_x = a._x;
_y = a._y;
}
string Point::ToString() const{
stringstream out;
out << "( " << _x << "," << _y << " )";
return out.str();
}
istream& operator>>(istream& in, Point* a) {
cout << "Nhap x: ";
in >> a->_x;
cout << "Nhap y: ";
in >> a->_y;
return in;
}
ostream& operator<<(ostream& out, const Point& a)
{
out << a.ToString();
return out;
}
```
class Rectangle
{
private:
Point* _topleft;
Point* _botright;
public:
void Set_topleft(Point tl) { _topleft = &tl; }
Point Get_topleft() { return *_topleft; }
void Set_botright(Point br) { _botright = &br; }
Point Get_botright() { return *_botright; }
public:
Rectangle();
Rectangle(Point*, Point*);
~Rectangle();
public:
string ToString() const;
public:
friend istream& operator>>(istream&, Rectangle&);
friend ostream& operator<<(ostream&, const Rectangle&);
};
Rectangle::Rectangle()
{
_topleft = new Point(0, 2);
_botright = new Point(3, 0);
}
Rectangle::Rectangle(Point* a, Point* b)
{
_topleft = new Point(*a);
_botright = new Point(*b);
}
Rectangle::~Rectangle()
{
delete _topleft;
delete _botright;
}
string Rectangle::ToString() const
{
stringstream out;
out << "A" << *_topleft << "+" << "D" << *_botright;
return out.str();
}
istream& operator>>(istream& in, Rectangle& a)
{
std::cout << "A( x,y ): ";
in >> a._topleft;
std::cout << "D( x,y ): ";
in >> a._botright;
return in;
}
ostream& operator<<(ostream& out, const Rectangle& a)
{
out << a.ToString();
return out;
}
```
template<class T>
class Array
{
private:
T* _a;
int _len;
public:
Array();
~Array();
public:
int length() { return _len; }
void PushBack(T);
T GetAt(int);
};
template<class T>
Array<T>::Array() {
_a = new T[128];
_len = 0;
}
template<class T>
Array<T>::~Array() {
delete[] _a;
_len = 0;
}
template<class T>
void Array<T>::PushBack(T value) {
if (_len >= 128)
{
std::cout << "Array is over size, which is 128\n";
return;
}
_a[_len] = value;
_len++;
}
template<class T>
T Array<T>::GetAt(int pos) {
return _a[pos];
}
```
The problem in your code is that when you PushBack the Rectangle object a into the array, you create copy of this object. This means that you just copy pointers _topleft and _botright. So in this part of code, you have 2 objects with the same pointers, so you're trying to delete twice the same part of memory.
To fix this you need to define own copy constructor, which will create new pointers in the new object.
Remember also to define own move constructors or make it disable for your class.
Rectangle(const Rectangle &other)
{
if(other._topleft)
_topleft= new Point(*other._topleft);
else
_topleft = nullptr;
if(other._botright)
_botright= new Point(*other._botright);
else
_topleft = nullptr;
}
The next problem is because of definition of void Array<T>::PushBack(T value). Please change it to the void Array<T>::PushBack(const T& value).
Also, try Rectangle(Rectangle&& o) = delete;
Added override for operator<< for my class but i am getting inside a function:
error: no match for ‘operator<<’ (operand types are
‘std::basic_ostream’ and ‘Edge’)
cout << "Adding: " << edge;
But if i try to use this code everything works as expected:
Edge edge1("A", "B", 3);
Edge* edge2 = new Edge("A", "B", 3);
cout << edge1 << endl;
cout << *edge2 << endl;
Here is code:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class Node {
public:
string name;
Node() {}
Node(string name):name(name) {}
bool operator==(const Node& other) {
return name == other.name;
}
};
class Edge {
public:
Node x;
Node y;
int cost;
Edge(string x_name, string y_name, int cost) {
this->x = Node(x_name);
this->y = Node(y_name);
this->cost = cost;
}
Edge(Node x, Node y, int cost):x(x),y(y) {}
bool operator==(const Edge& other) {
return x == other.x && x == other.y && cost == other.cost;
}
};
class Graph {
public:
vector<Edge> edges;
vector<Node> nodes;
bool has_node(Node node) {
return find(nodes.begin(), nodes.end(), node) != nodes.end();
}
bool has_edge(Edge edge) {
return find(edges.begin(), edges.end(), edge) != edges.end();
}
void add(string x_name, string y_name, int cost) {
Node x(x_name);
Node y(y_name);
bool has_not_x = !has_node(x);
bool has_not_y = !has_node(y);
if (has_not_x) {
nodes.push_back(x);
}
if (has_not_y) {
nodes.push_back(y);
}
if (has_not_x || has_not_y) {
add(x, y, cost);
}
}
void add(Node x, Node y, int cost) {
Edge edge(x, y, cost);
if (!has_edge(edge)) {
cout << "Adding: " << edge;
edges.push_back(edge);
}
}
};
ostream& operator<<(ostream& os, const Node& node)
{
os << "(" << node.name << ")";
return os;
}
ostream& operator<<(ostream& os, const Edge& edge)
{
os << edge.x << "-" << edge.cost << "-" << edge.y;
return os;
}
int main()
{
Graph* graph = new Graph();
graph->add("A", "C", 1);
return 0;
}
Because the compiler reads the code linearly, it is not aware that the overload of operator<<(ostream&, const Edge&) exists yet.
If you place a declaration of the overload before the definition of the class, the code will compile:
// Place the function declaration before the class
// to inform the compiler of the overload's existence.
ostream& operator<<(ostream& os, const Edge& edge);
class Graph {
public:
vector<Edge> edges;
vector<Node> nodes;
// and so on...
Say I have a simple vector class, vec:
#include <iostream>
#include <stdlib.h>
class vec {
public:
vec() {}
// Constructor.
vec(int n) {
len = n;
data = new double[len];
}
// Destructor.
~vec() { delete [] data; }
// Accessor.
double & operator[](int i) const {
check_index(i);
return data[i];
}
// Other methods...
// ....
protected:
int len;
double * data;
void check_index(int i) const {
if(i < 0 || i >= len) {
std::cerr << "Bad access.\n";
exit(1);
}
}
};
Now suppose I have a special type of vector with sparse structure, e.g., where every even-index is zero. Call this oddvec. Instances of oddvec should be declared just as with the vec class, but underneath, the memory use should be efficient since only half the data is non-zero.
The accessor for the oddvec class should return 0 if the index is even, and return the odd-index element (stored sequentially) otherwise. There a couple problems with this:
The double & return type is violated if the index is even, since the constant value, 0, is returned.
It's not clear to me how to handle the situation when an even index element is used as an lvalue. E.g., v[0] = 3.0 should not be allowed in the oddvec class, but is perfectly acceptable in the vector class. We can't simply throw an error when even indexes are used, because even indexes are fine as long as the intention is as an rvalue.
How do I design the accessor function for the oddvec class, while both keeping the memory storage efficient and inheriting all the methods from the parent?
Non-working example of oddvec:
class oddvec : public vec {
public:
// Constructor.
oddvec(int n) {
len = n;
data = new double[len/2];
}
// Accessor (doesn't work!)
double & operator[](int i) const {
check_index(i);
if (i%2 == 0)
return 0;
else
return data[(i-1)/2];
}
};
Upon compilation:
main.cpp: In member function ‘double& oddvec::operator[](int) const’:
main.cpp:49:20: error: invalid initialization of non-const reference of type ‘double&’ from an rvalue of type ‘double’
return 0;
Working example using proxy classes:
I have implemented a proxy class as suggested in the answer below.
proxies.h
#ifndef PROXIES_H
#define PROXIES_H
#include <iostream>
#include <stdlib.h>
class proxy {
public:
proxy(int i, double v, double * d) {
index = i;
value = v;
data = d;
}
void operator=(double rhs) {
data[index] = rhs;
}
friend std::ostream & operator<<(std::ostream & outs, const proxy & p) {
outs << p.value;
return outs;
}
protected:
int index;
double value;
double * data;
};
class oddproxy : public proxy {
public:
oddproxy(int i, int v, double * d) : proxy(i, v, d) {}
void operator=(double rhs) {
if (index%2 == 0) {
std::cerr << "Even entries of oddvec are not assignable.\n";
exit(1);
}
data[index/2] = rhs;
}
};
#endif
vectors.h
#ifndef VECTORS_H
#define VECTORS_H
#include "proxies.h"
class vec {
public:
vec() {}
// Constructor.
vec(int n) {
len = n;
data = new double[len];
}
// Destructor.
~vec() { delete [] data; }
// Accessor.
proxy operator[](int i) const {
check_index(i);
return proxy(i, data[i], data);
}
inline int length() const { return len; }
// Other methods...
// ....
protected:
int len;
double * data;
void check_index(int i) const {
if(i < 0 || i >= len) {
std::cerr << "Bad access.\n";
exit(1);
}
}
};
class oddvec : public vec {
public:
// Constructor.
oddvec(int n) {
len = n;
data = new double[len/2];
}
// Accessor.
oddproxy operator[](int i) const {
check_index(i);
return oddproxy(i, (i%2 == 0) ? 0 : data[i/2], data);
}
};
#endif
main.cpp
#include <iostream>
#include "vectors.h"
int main () {
int N = 5;
vec V(N);
oddvec O(N);
for(int i=0; i < V.length(); i++) {
V[i] = i;
if(i%2 != 0) {
O[i] = i;
}
}
for(int i=0; i < O.length(); i++) {
std::cout << "V[" << i << "]=" << V[i] << ", "
<< "O[" << i << "]=" << O[i] << "\n";
}
O[0] = 13;
return 0;
}
output
V[0]=0, O[0]=0
V[1]=1, O[1]=1
V[2]=2, O[2]=0
V[3]=3, O[3]=3
V[4]=4, O[4]=0
Even entries of oddvec are not assignable.
You can use proxy object to do this.
simple sample code:
#include <iostream>
#include <vector>
using namespace std;
class very_odd_vector{
public:
class only_odd_proxy;
friend class only_odd_proxy;
only_odd_proxy operator [](int index);
int operator [](int index)const{return index%2==0?0:content[index/2];}
unsigned int size()const{return content.size()*2;}
private:
vector<int> content{1,3,5,7,9};
};
class very_odd_vector::only_odd_proxy{
public:
only_odd_proxy(very_odd_vector& vec,int index):vec(vec),index(index){}
operator int(){return index%2==0 ? 0 : vec.content[index/2];}
only_odd_proxy& operator =(int value){
if(index%2==0)
cout << "BAD OPERATION";//any error you want
else
vec.content[index/2] = value;
return *this;
}
private:
very_odd_vector& vec;
int index;
};
auto very_odd_vector::operator [](int index)->only_odd_proxy{return only_odd_proxy(*this,index);}
int main(){
very_odd_vector v;
cout << "reading value\n";
for(int i=0;i<v.size();++i)
cout << v[i] <<'\n';
cout << "writting value\n";
for(int i=0;i<v.size();++i){
cout << i << ':';
v[i]=10;
cout << '\n';
}
cout << "reading value\n";
for(int i=0;i<v.size();++i)
cout << v[i] <<'\n';
}
Edit for updated part of question :
I think this class will fit your need more.
//Both base and inherit class return this class
class maybe_readonly_proxy {
public:
maybe_readonly_proxy(double* data, bool readonly):readonly(readonly),data(data){}
maybe_readonly_proxy& operator=(double rhs) {
if(readonly){/*whatever error*/}
else {*data = rhs;}
return *this;
}
operator double()const{return *data;}
private:
bool readonly;
double * data;
};
You may need a variable to contain readonly (0 in this case) value, or modify the operator double() the check readonly state
Or just implement get and set method separately and do not use this proxy may be another choice.
Hi I am trying to debug a program and one of the errors I am receiving is 'Missing Initialization for Constructor'. Do I need to declare the vector upfront and how do I initialize it?
#include <iostream>
#include <vector>
using namespace std;
class Point {
private:
double x;
double y;
public:
double get_x() { return x; }
double get_y() { return y; }
bool set_x(double arg) {
x = arg;
return true;
}
bool set_y(double arg) {
y = arg;
return true;
}
Point() : x(0), y(0) {}
Point(double argx, double argy) : x(argx), y(argy) {
}
};
class Vector {
private:
Point A;
Point B;
public:
Point get_A() { return A; }
Point get_B() { return B; }
Vector(const Point &arg1, const Point &arg2) : A(arg1), B(arg2)
{
//this->A = arg1;
//this->B = arg2;
//A = arg1;
//B = arg2;
}
void set_A(const Point &arg) {
A = arg;
}
void set_B(const Point &arg) {
B = arg;
}
static Vector add_vector(const Vector &vector1, const Vector &vector2) {
if (&vector1.B != &vector2.A) {
//Error 1 Vector V1 No Matching constructor for initialization for 'vector'
Vector rval;
return rval;
}
Point one = vector1.A;
Point two = vector2.B;
Vector newvector(one, two);
//newvector.A = one;
//newvector.B = two;
return newvector;
}
Vector add_vector(const Vector &arg) {
// Type of this? Vector *; These three lines are equivalent:
//Point one = this->A;
//Point one = (*this).A;
Point one = A;
Point two = arg.B;
Vector newvector(one, two);
//newvector.A = one;
//newvector.B = two;
return newvector;
}
};
int main() {
//Error 2 Vector v No Matching constructor for initialization for 'vector'
Vector v;
cout << "(" << v.get_A().get_x() << ", " << v.get_A().get_y() << "),\n" <<
"(" << v.get_B().get_x() << ", " << v.get_B().get_y() << ")\n";
//Error 3 Vector V1 No Matching constructor for initialization for 'vector'
Vector v1(1,2), v2(2,3);
Vector res = Vector::add_vector(v1, v2);
cout << "(" << res.get_A().get_x() << ", " << res.get_A().get_y() << "),\n" <<
"(" << res.get_B().get_x() << ", " << res.get_B().get_y() << ")\n";
}
Your issue here is your class is not default constructable.
Vector rval;
Requires a default constructor. Since you provided a user defined constructor the compiler will no longer make a default constructor for you.
To create a default constructor for Vector you can use
Vector() = default;
If you have C++11 or higher or you can use
Vector() {}
For pre C++11.
I am not sure what you are trying to do with
Vector v1(1,2)
Vector needs two Points and each Point needs 2 values.
I'm using a class 'triangle' which is expressed as a vector of type 'vertex', 'vertex' being a structure consisting of an x and y value. I have a member function in 'triangle' that is supposed to return the area using heron's formula. Everything works fine until I try to output the area in the main function. Here is my code
vertex.h file
#ifndef VERTEX_H
#define VERTEX_H
#include <iostream>
struct vertex
{
double x, y;
vertex(double ix = 0.0, double iy = 0.0)
{
x = ix;
y = iy;
}
};
#endif // VERTEX_H
triangle.h file
#ifndef TRIANGLE_H
#define TRIANGLE_H
#include <iostream>
#include <vector>
#include "vertex.h"
class triangle
{
public:
triangle(vertex iv0 = vertex(), vertex iv1 = vertex(), vertex iv2 = vertex());
// pre:
// post: empty triangle
triangle(const triangle & source);
// pre:
// post: triangle created and initialized to given triangle source
vertex operator[](size_t i) const;
// pre: 0 <= i < 3
// post: return vertex i in this triangle
double area() const;
//pre:
//post: returns area of triangle
private:
std::vector<vertex> v;
};
std::ostream & operator << (std::ostream & os, const triangle & p);
std::istream & operator >> (std::istream & is, triangle & p);
#endif // TRIANGLE.H
triangle.cpp file
#include <cassert>
#include <vector>
#include <math.h>
#include "triangle.h"
triangle::triangle(vertex iv0, vertex iv1, vertex iv2) : v(3)
{
v[0] = iv0;
v[1] = iv1;
v[2] = iv2;
}
triangle::triangle(const triangle &p)
{
v = p.v;
}
vertex triangle::operator[] (std::size_t i) const
{
assert(i < v.size());
return v[i];
}
double triangle::area() const
{
double a, b, c;
double s;
a = sqrt(pow((v[0].x-v[1].x), 2)+pow((v[0].y-v[1].y), 2));
b = sqrt(pow((v[1].x-v[2].x), 2)+pow((v[1].y-v[2].y), 2));
c = sqrt(pow((v[2].x-v[0].x), 2)+pow((v[2].y-v[0].y), 2));
s = (a+b+c)/2;
return sqrt(s*(s-a)*(s-b)*(s-c));
}
//PROBLEM IS HERE^
//(used distance formula to find side lengths a, b, and c)
main function
#include <iostream>
#include "triangle.h"
using namespace std;
int main()
{
triangle t;
t[0] = vertex(2,3);
t[1] = vertex(5,4);
t[2] = vertex(3,7);
cout << t << endl;
cout << t.area() << endl;
cout << t.operator [](2) << endl;
return 0;
}
Since you are initialising your triangle using operator[], you need to make a non-const version of that function that returns a reference. Generally you return a const reference from the const version too, rather than by value:
const vertex& triangle::operator[] (std::size_t i) const
{
assert(i < v.size());
return v[i];
}
vertex& triangle::operator[] (std::size_t i)
{
assert(i < v.size());
return v[i];
}
Your compiler really shouldn't have let you get away with the code you posted. Modifying an rvalue should be an error, or at the very least a warning. Make sure you compile with warnings turned on, and read them!
The issue has to do with how you are initializing the triangle object. Try initializing it this way:
int main()
{
triangle t (vertex(2,3), vertex(5,4), vertex(3,7));
cout << t.area() << endl;
return 0;
}
Another less ideal solution would be to make "v" a public member and then assign the values this way:
triangle t;
t.v[0] = vertex(2,3);
t.v[1] = vertex(5,4);
t.v[2] = vertex(3,7);