Polymorphic calls not working!!
Jul 24, 2017 at 7:19pm UTC
Shape<---Triangle<---IsoTriangle
If I run code below I get the following error
IsoTriangle.cpp:36:8: error: no match for ‘operator<<’ (operand types are ‘std::ostream {aka std::basic_ostream<char>}’ and ‘Shape’)
cout << *shp << endl;
1 2 3 4 5 6 7 8 9
IsoTriangle rect(10);
Shape* shp = ▭
//cout << typeid(shp).name() << endl;
//cout << typeid(*shp).name() << endl;
//This line causes error saying compiler cannot find operator<<
cout << *shp << endl;
//rect.draw('2', 'w');
}
My Shape header
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
#ifndef SHAPE_H
#define SHAPE_H
#include<string>
#include<vector>
#include<iostream>
using namespace std;
class Shape {
private :
static int num;
int id_num;
string generic_name;
string descriptive_name;
public :
vector< vector<char > > str_rep;
//getters
virtual int get_id() const ;
virtual string get_generic_name() const ;
virtual string get_descriptive_name() const ;
int num_incr();
//setters
virtual void set_generic_name(string name);
virtual void set_desciptive_name(string name);
virtual void set_id(int id);
//pure_virtuals
virtual void generate_string_representation() = 0;
virtual void scale(int factor) = 0;
virtual float area() const = 0;
virtual float perimeter() const = 0;
virtual vector< vector<char > > draw(char penChar, char fillChar) const = 0;
virtual float calculate_box_height() const = 0;
virtual float calculate_box_width() const = 0;
virtual float scrn_area() const = 0;
virtual float scrn_perimeter() const = 0;
virtual string toString() const = 0;
// friend ostream& operator<<(ostream& os, const vector< vector<char> >& grid);
// friend ostream& operator<<(ostream& os, const Shape& obj);
};
#endif
Shape cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
#include"Shape.h"
int Shape::num = 0;
int Shape::get_id() const {
return this ->id_num;
}
string Shape::get_generic_name() const {
return this ->generic_name;
}
string Shape::get_descriptive_name() const {
return this ->descriptive_name;
}
int Shape::num_incr() {
Shape::num++;
return Shape::num;
}
void Shape::set_generic_name(string name) {
this ->generic_name = name;
}
void Shape::set_desciptive_name(string name) {
this ->descriptive_name = name;
}
void Shape::set_id(int id) {
this ->id_num = id;
}
My triangle header
1 2 3 4 5 6 7 8 9
#ifndef TRIANGLE_H
#define TRIANGLE_H
#include"Shape.h"
class Triangle: public Shape{
};
#endif
IsoTriangle.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
#ifndef IsoTriangle_H
#define IsoTriangle_H
#include"Triangle.h"
#include<typeinfo>
#include<string>
#include <cmath>
class IsoTriangle : public Triangle {
public :
int height;
int base;
IsoTriangle(int base);
~IsoTriangle();
void generate_string_representation(){
this ->str_rep.resize(this ->height);
int point = (this ->base / 2) ;
int count = 0;
for (int x = 0; x <= this ->height - 1; x++) {
this ->str_rep[x].resize(this ->base);
for (int y = 0; y <= this ->base - 1; y++) {
if (y >= point - count && y<= point + count){
this ->str_rep[x].push_back('*' );
}else {
this ->str_rep[x].push_back(' ' );
}
}
count++;
}
}
void scale(int factor) {
if (this ->base + (2 * factor) >= 1) {
this ->base = this ->base + (2 * factor);
this ->height = (this ->base + 1)/2;
this ->generate_string_representation();
}
}
float area() const {
return float (float (this ->height * this ->base)/2);
}
float perimeter() const {
int b_sq = this ->base * this ->base;
int h_sq = this ->height * this ->height;
return float (this ->base + (2 * pow(((.25 * b_sq) + h_sq), .5)));
}
vector< vector<char > > draw(char penChar, char fillChar) const {
const int b = this ->base;
const int h = this ->height;
vector< vector<char > > temp(h, vector<char >(b));
int point = (this ->base / 2) ;
int count = 0;
for (int x = 0; x <= this ->height - 1; x++) {
for (int y = 0; y <= this ->base - 1; y++) {
if (y >= point - count && y<= point + count){
temp[x].push_back(penChar);
}else {
temp[x].push_back(fillChar);
}
}
count++;
}
return temp;
}
float calculate_box_height() const {
return this ->height;
}
float calculate_box_width() const {
return this ->base;
}
float scrn_area() const {
return float (this ->height * this ->height);
}
float scrn_perimeter() const {
return float (4 * (this ->height - 1));
}
string toString() const {
string abcd;
abcd = string("Shape Information" ) + "\n" ;
abcd = abcd + "-----------------" + "\n" ;
abcd = abcd + "Static type: " + typeid (this ).name() + "\n" ;
abcd = abcd + "Dynamic type: " + typeid (this ).name() + "\n" ;
abcd = abcd + "Generic Name: " + this ->get_generic_name() + "\n" ;
abcd = abcd + "Description: " + this ->get_descriptive_name() + "\n" ;
abcd = abcd + "id: " + to_string(this ->get_id()) + "\n" ;
abcd = abcd + "B. box width: " + to_string(this ->calculate_box_width()) + "\n" ;
abcd = abcd + "B. box height: " + to_string(this ->calculate_box_height()) + "\n" ;
abcd = abcd + "Scr area: " + to_string(this ->scrn_area()) + "\n" ;
abcd = abcd + "Geo area: " + to_string(this ->area()) + "\n" ;
abcd = abcd + "Scr Perimeter: " + to_string(this ->scrn_perimeter()) + "\n" ;
abcd = abcd + "Geo Perimeter: " + to_string(this ->perimeter()) + "\n" ;
return abcd;
}
friend ostream& operator <<(ostream& os, const Shape& obj) {
os << "Shape Information" << endl;
os << "-----------------" << endl;
os << "Static type: " << typeid (&obj).name() << endl;
os << "Dynamic type: " << typeid (obj).name() << endl;
os << "Generic Name: " << obj.get_generic_name() << endl;
os << "Description: " << obj.get_descriptive_name() << endl;
os << "id: " << obj.get_id() << endl;
os << "B. box width: " << obj.calculate_box_width() << endl;
os << "B. box height: " << obj.calculate_box_height() << endl;
os << "Scr area: " << obj.scrn_area() << endl;
os << "Geo area: " << obj.area() << endl;
os << "Scr Perimeter: " << obj.scrn_perimeter() << endl;
os << "Geo Perimeter: " << obj.perimeter() << endl;
return os;
}
};
ostream& operator <<(ostream& os, const vector< vector<char > >& grid) {
for (const vector<char >& vec : grid) {
for (const char & ch : vec) {
os << ch;
}
os <<"\n" ;
}
return os;
}
#endif // !IsoTriangle_H
IsoTriangle.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
#include "IsoTriangle.h"
#include <iostream>
IsoTriangle::IsoTriangle(int base) {
if (base<=0){
std::cout << "Cannot pass values less than or equal to 0 \n" ;
this ->~IsoTriangle();
}
if (base%2==0){
base++;
}
this ->base = base;
this ->height = (base + 1)/2;
this ->set_id(this ->num_incr());
this ->set_generic_name("IsoTriangle" );
this ->set_desciptive_name("Generic IsoTriangle" );
}
IsoTriangle::~IsoTriangle() {
}
int main()
{
IsoTriangle rect(10);
IsoTriangle rect_1(0);
IsoTriangle rect_2(-10);
cout << rect << endl;
cout << rect.draw('2' , 'w' ) << endl;
rect.scale(2);
cout << rect.draw('2' , 'w' ) << endl;
cout << rect.toString() << endl;
Shape* shp = ▭
cout << typeid (shp).name() << endl;
cout << typeid (*shp).name() << endl;
cout << *shp << endl;
//rect.draw('2', 'w');
}
Jul 24, 2017 at 7:39pm UTC
There is no operator<< that takes a Shape as argument.
Jul 24, 2017 at 11:49pm UTC
There is operator<< with Shape argument somehow its indented badly IDK why
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
friend ostream& operator <<(ostream& os, const Shape& obj) {
os << "Shape Information" << endl;
os << "-----------------" << endl;
os << "Static type: " << typeid (&obj).name() << endl;
os << "Dynamic type: " << typeid (obj).name() << endl;
os << "Generic Name: " << obj.get_generic_name() << endl;
os << "Description: " << obj.get_descriptive_name() << endl;
os << "id: " << obj.get_id() << endl;
os << "B. box width: " << obj.calculate_box_width() << endl;
os << "B. box height: " << obj.calculate_box_height() << endl;
os << "Scr area: " << obj.scrn_area() << endl;
os << "Geo area: " << obj.area() << endl;
os << "Scr Perimeter: " << obj.scrn_perimeter() << endl;
os << "Geo Perimeter: " << obj.perimeter() << endl;
return os;
}
Last edited on Jul 25, 2017 at 12:35am UTC
Jul 25, 2017 at 11:11am UTC
Ah, I see. I wasn't expecting it to be in the IsoTriangle class.
When you declare a function as a friend inside a class it will not be considered during the usual lookup process outside the class.
1 2 3 4 5 6 7 8 9 10
class A
{
friend void f();
};
int main()
{
A a;
f(); // error: ‘f’ was not declared in this scope
}
The reason it normally works for the << and >> operators is thanks to something called
argument-dependent lookup (ADL). If a class object is passed as argument to a function the compiler will in addition look for a matching function within that class.
1 2 3 4 5 6 7 8 9 10
class A
{
friend void g(A);
};
int main()
{
A a;
g(a); // This works fine thanks to ADL.
}
In your code you are passing a Shape reference to the << operator but it cannot find a match. There is no such operator declared in the global scope, nor is it in the Shape class. The IsoTriangle class is not considered.
Topic archived. No new replies allowed.