LINUX.ORG.RU

Как указать параметры которые еще не известны

 


0

2

Добрый день. Возникла задача, которую не знаю как решить.
Есть ряд объектов (b,c), у которых есть переменные (x,y,...).
Нужно, например, напечатать все переменные этих объектов.
Чтобы сократить код пытаюсь все обернуть в одну процедуру print.
Но есть проблема: нужно передать какой параметр печатать, а цикл по самим объектам содержится с подпрограмме.
Можно ли как-нибудь извернуться и это сделать? Может вы уже с таким сталкивались?

Ниже представлен код:

#include <iostream>
#include <vector>

using namespace std;

class A {
public:
    double x, y;
    virtual void print(double a) = 0;
    virtual ~A() {}
};

class B: public A {
public:
    void print(double a) {
        std::cout << a << std::endl;
    }
};

class C: public A {
public:
    void print(double a) {
        std::cout << a << std::endl;
    }
};

void print(vector<A*> v,double a)
{
    A *e;

    for(vector<A*>::iterator it=v.begin(); it!=v.end(); ++it) {
        e = *it;
        // другие вычисления
        e->print(a);
    }
}

int main() {
    vector<A*> v;
    A *e;
    B b;
    C c;
    b.x=1;
    b.y=2;
    c.x=3;
    c.y=4;

    v.push_back(&b);
    v.push_back(&c);

    print(v,x); // здесь ошибка
    print(v,y); // здесь ошибка

    return 0;
}

★★★★★

Последнее исправление: cetjs2 (всего исправлений: 1)

Наркоман вы, батенька.

double x, y;

std::cout << a << std::endl;

в чем суть?

    print(v,x); // здесь ошибка
    print(v,y); // здесь ошибка

разумеется. Что такое x и y?

anonymous
()

Не делай print виртуальной, передавай в неё флаг какое поле печатать.

class A {
public:
    enum PrintWhat { PRINT_A, PRINT_X, PRINT_Y };
    double x, y;
    void print(double a, PrintWhat what = PRINT_A) {
        switch(what) {
        case PRINT_A: std::cout << a << std::endl; return;
        case PRINT_X: std::cout << x << std::endl; return;
        case PRINT_Y: std::cout << y << std::endl; return;
        }
    }
    virtual ~A() {}
};
slovazap ★★★★★
()
Ответ на: комментарий от anonymous

Что поделать задача такая.

double x, y; // на самом деле там предполагается в дальнейшем массив.

Суть такая: в зависимости от метода задачи нужно печатать разное количество переменных (x,y,z,...) для каждого класса.

Zodd ★★★★★
() автор топика

Это же называют интроспекцией, да? Заведи для полей std::map<keytype, double> и обращайся к ним по ключам, хоть по строкам, хоть по именованным константами. Тогда сможешь по этому контейнеру итерироваться.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

Вот из двух процедур нужно сделать одну

void printX(vector<A*> v)
{
    A *e;

    for(vector<A*>::iterator it=v.begin(); it!=v.end(); ++it) {
        e = *it;
        // другие вычисления
        e->print(e->x);
    }
}

void printY(vector<A*> v)
{
    A *e;

    for(vector<A*>::iterator it=v.begin(); it!=v.end(); ++it) {
        e = *it;
        // другие вычисления
        e->print(e->y);
    }
}

Можно ли это без std::map обойтись или все же придется?

Zodd ★★★★★
() автор топика
Ответ на: комментарий от Zodd

От такого объяснения стало ещё непонятнее.

i-rinat ★★★★★
()

ЯННП

что мешает в наследниках сделать

class B: public A {
    double z, y, z;
public:
    void print(double a) {
        std::cout << x << y << z << std::endl;
    }
};

?

anonymous
()
Ответ на: комментарий от Zodd

Если я правильно понял, ты хочешь функцию, желательно определённую один раз, в родителе, которая в курсе, какие поля есть у класса-потомка. Прямых способов это сделать нет. Либо делай поля итерируемыми и используй одну общую функцию, либо создай специализированную функцию для каждого класса. Второй вариант можно как-нибудь генерировать автоматически, чтобы не писать руками простыни кода.

i-rinat ★★★★★
()

Оно (см. ответ с 4 плюсами, где буст предложили)?

Eddy_Em ☆☆☆☆☆
()

Поддерживаю, std::map юзай.

Еще можно boost.fusion глянуть.

Но сформулирована задача непонятно

Deleted
()
Ответ на: комментарий от Deleted

Могу словами изложить саму задачу.

Есть объект 1, состоящий из прямоугольников, в вершинах которых хранятся некоторые значения. Есть объект 2, состоящий из прямых, тоже в узлах хранятся некоторые значения (например, вес). Эти узловые значения хранятся в виде массива. Объектов может быть несколько. Нужно напечатать эти значения (вес, и другие значения) в файл.

Zodd ★★★★★
() автор топика
Ответ на: комментарий от Zodd

Если у тебя иерархия классов и полиморфизм, то понадобится виртуальная функция à la PrintMe, каждый класс реализует эту функцию в соответствии со своими особенностями. Если полиморфизма нет и ты в каждый момент точно знаешь тип объекта, то достаточно завести operator<<.

Gvidon ★★★★
()
Ответ на: комментарий от Zodd

Вроде обычный логгинг или дебажная печать объектов. У каждого элементарного объекта пусть будет метод sprint()

struct Point {
int x, y;
std::string sprint(int level) const
{
     std::stringstrream ss; 
     if(level == FULL)
         ss << "Point{" << x << "," << y << "}";
     else
         ss <<  x;
    return ss.str();
}
};

У каждого составного объекта будет тоже метод sprint(), в котором вызываются методы sprint() всех внутренних объектов

struct Shape {
Point a, z;
std::string sprint(int level) const
{
    std::stringstrream ss;
    if(level == FULL)
        ss << "Shape{a:" << a.sprint(level) << ", b:" << b.sprint(level) <<"}"; 
    else
       ss << b.sprint(level);
    return ss.str();
}
}

А параметром level (или назвать его по другому, если смысл другой: verbose, format) регулируется степень многословности, или формат вывода, насквозь, по всей рекурсивной иерархии вызовов sprint() объекта, начиная с самого верхнего уровня

PS. считаю, что перегружать operator<<() - излишне, особенно если печать нужно параметризировать.

Deleted
()
Последнее исправление: Deleted (всего исправлений: 3)
Ответ на: комментарий от Zodd

Вот собственно вот так пока выкрутился

#include <iostream>
#include <vector>

using namespace std;

class A {
public:
    double x, y;
    virtual void print(double p) = 0;
    virtual ~A() {}
};

class B: public A {
public:
    void print(double p) {
        std::cout << p << std::endl;
    }
};

class C: public A {
public:
    void print(double p) {
        std::cout << p << std::endl;
    }
};

void print(A* e,double p) {
    e->print(p);
}

int main() {
    vector<A*> v;
    A *e;
    B b;
    C c;
    b.x=1;
    b.y=2;
    c.x=3;
    c.y=4;

    v.push_back(&b);
    v.push_back(&c);

    for(vector<A*>::iterator it=v.begin(); it!=v.end(); ++it) {
        e = *it;
        print(e,e->x);
        print(e,e->y);
    }

    return 0;
}
Zodd ★★★★★
() автор топика

полистай Страуструпа Дизайн...

ну и конкурентно с дизайн&философия полистай его-же(Бьёрново) Программирование. Принципы и практика использования C++

зы. ох уж эти устьурюпинские ооп.

qulinxao ★★☆
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.