Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 16.11.2012, 01:17   #1
sectors70
Пользователь
 
Регистрация: 15.04.2012
Сообщений: 20
По умолчанию Проблема с приведением типа базового класса к типу дочернего

Всем привет. Скорее всего, из названия темы ничего непонятно, поэтому попробую объяснить.
Во-первых, я хочу создать 2 класса - класс матрицы и класс вектора, который будет унаследован от класса матриц. Ну и конечно, нужно перегрузить все математические операторы.
Вот некоторые методы:
Код:
class Matrix
{
protected:
    int height; // количество строк
    int width; // количество столбцов
    double** data; // массив для хранения самой матрицы

public:
    Matrix() {this->data = NULL; this->width = this->height = 0; };
    Matrix(int w, int h); // создает пустую матрицу заданного размера
    Matrix operator-(Matrix m); // оператор "-", для матриц работает нормально
};
Вот класс вектора:
Код:
class Vector : public Matrix
{
public:
    Vector() : Matrix() {};
    Vector(int s) : Matrix(1, s) {}; //просто создается матрица с одним столбцом
    Vector operator-(Vector v);
};
Я опустил некоторые неважные в данном вопросе методы.

Проблема вот в чем:
Пытаюсь перегрузить оператор вычитания для вектора:
Код:
Vector Vector::operator-(Vector v)
{
    return (Matrix)*this - (Matrix)v;
}
В этом то методе компилятор и выдает ошибку: conversion from 'Matrix' to non-scalar type 'Vector' requested
То есть получается, он не может преобразовать тип Matrix в Vector. Повторюсь, для матриц этот оператор работает прекрасно и возвращает Matrix
Подскажите, как правильно написать?
Не хотелось бы для класса Vector опять перегружать все операторы, тогда уж и смысл наследования пропадает. Если нужно что-нибудь уточнить по коду - спрашивайте . Спасибо.

Последний раз редактировалось sectors70; 16.11.2012 в 02:22.
sectors70 вне форума Ответить с цитированием
Старый 16.11.2012, 02:42   #2
sectors70
Пользователь
 
Регистрация: 15.04.2012
Сообщений: 20
По умолчанию

как-то, окольными путями и костылями получилось сделать такую вещь:
Код:
Vector Vector::operator-(Vector v)
{
    Matrix m = (Matrix)*this - (Matrix)v;
    return static_cast<Vector&>(m);
}
Но я и сам понимаю, что это не дело. Должно же оно как-то решаться по-красивее!
Причем такая конструкция не работала: return static_cast<Vector&>( (Matrix)*this - (Matrix)v );

Честно признаться, я не понимаю, что тут происходит. Помогите разобраться, пожалуйста

Последний раз редактировалось sectors70; 16.11.2012 в 02:45.
sectors70 вне форума Ответить с цитированием
Старый 16.11.2012, 08:24   #3
Abstraction
Старожил
 
Аватар для Abstraction
 
Регистрация: 25.10.2011
Сообщений: 3,178
По умолчанию

Проблема в том, что вычитание матриц у Вас порождает матрицу. Разумеется, не любая матрица является "вектором" (в смысле - матрицей nx1), вот компилятор и теряется. Как вариант - определите в классе матриц Matrix :: operator(Vector)(void)const; - тогда компилятор будет просто его вызывать, и всем будет хорошо.

Последний раз редактировалось Abstraction; 16.11.2012 в 08:24. Причина: Смайлики ;(
Abstraction вне форума Ответить с цитированием
Старый 16.11.2012, 10:06   #4
Helloween
Форумчанин
 
Регистрация: 24.04.2012
Сообщений: 300
По умолчанию

Ну вообще для этого есть dynamic_cast, но он работает только с указателями и с полиморфными классами.
Т.о тебе в классе Matrix нужно объявить любой виртуальный метод, например:
Код:
virtual void stub();
Ну и переписать оператор:
Код:
Vector Vector::operator-(Vector v)
{
    return *dynamic_cast<Vector*>(&((Matrix)*this - (Matrix)v));
}
Помог? Оставляем отзыв =)

Последний раз редактировалось Helloween; 16.11.2012 в 10:10.
Helloween вне форума Ответить с цитированием
Старый 16.11.2012, 10:22   #5
Abstraction
Старожил
 
Аватар для Abstraction
 
Регистрация: 25.10.2011
Сообщений: 3,178
По умолчанию

Helloween, вернёт NULL. Ибо Matrix :: operator- возвращает объект, не являющийся объектом класса Vector.
Abstraction вне форума Ответить с цитированием
Старый 17.11.2012, 23:53   #6
sectors70
Пользователь
 
Регистрация: 15.04.2012
Сообщений: 20
По умолчанию

Цитата:
Сообщение от Abstraction Посмотреть сообщение
Проблема в том, что вычитание матриц у Вас порождает матрицу. Разумеется, не любая матрица является "вектором" (в смысле - матрицей nx1), вот компилятор и теряется. Как вариант - определите в классе матриц Matrix :: operator(Vector)(void)const; - тогда компилятор будет просто его вызывать, и всем будет хорошо.
Извините, не могли бы вы по яснее написать про Matrix :: operator(Vector)(void)const; , я не до конца понимаю, что это это означает. Там именно operator? без минуса? Вообще если поставить минус, то компилятор пишет, что operator- объявлена как функция, возвращающая функцию. Можете отправить читать литературу . А вообще я думал, что раз вектор частный случай матрицы, почему бы не привести его к типу матрицы. Как же я был наивен
sectors70 вне форума Ответить с цитированием
Старый 17.11.2012, 23:56   #7
sectors70
Пользователь
 
Регистрация: 15.04.2012
Сообщений: 20
По умолчанию

Цитата:
Сообщение от Helloween Посмотреть сообщение
Ну вообще для этого есть dynamic_cast, но он работает только с указателями и с полиморфными классами.
Т.о тебе в классе Matrix нужно объявить любой виртуальный метод, например:
Код:
virtual void stub();
Ну и переписать оператор:
Код:
Vector Vector::operator-(Vector v)
{
    return *dynamic_cast<Vector*>(&((Matrix)*this - (Matrix)v));
}
Программа вылетает при использовании операции "-". при компиляции выдает warning та той строке, которую вы посоветовали: taking address of temporary
sectors70 вне форума Ответить с цитированием
Старый 18.11.2012, 00:59   #8
Abstraction
Старожил
 
Аватар для Abstraction
 
Регистрация: 25.10.2011
Сообщений: 3,178
По умолчанию

Цитата:
Извините, не могли бы вы по яснее написать про Matrix :: operator(Vector)(void)const; , я не до конца понимаю, что это это означает. Там именно operator? без минуса? Вообще если поставить минус, то компилятор пишет, что operator- объявлена как функция, возвращающая функцию. Можете отправить читать литературу . А вообще я думал, что раз вектор частный случай матрицы, почему бы не привести его к типу матрицы. Как же я был наивен
Начну с конца. Вектор - случай матрицы, но матрица - не случай вектора. Вы определили операцию "вычитание", которая из двух матриц получает матрицу. Её можно применить к двум векторам и получить на выходе... правильно, матрицу (сравните с умножением). То, что "на самом деле" при сложении векторов получится не просто матрица, а вектор, знаете Вы, но не компилятор. Компилятору надо как-то об этом сказать. Например, можно переопределить ещё один оператор - оператор приведения типа (см. учебник/справку/whatever). При этом, возможно, потребуется явно указать, что выполняется приведение матрицы к вектору:
Код:
Vector Vector::operator-(Vector v)
{
    return (Vector)((Matrix)*this - (Matrix)v);
}
Сравните это с точки зрения синтаксиса с таким кодом:
Код:
float a=3.87, b=7.34;
int s = (int)(a+b);
Abstraction вне форума Ответить с цитированием
Старый 18.11.2012, 01:15   #9
sectors70
Пользователь
 
Регистрация: 15.04.2012
Сообщений: 20
По умолчанию

Спасибо, я понял. Просто я сразу не догадался, что это переопределение оператора приведения типа.
sectors70 вне форума Ответить с цитированием
Старый 18.11.2012, 18:36   #10
sectors70
Пользователь
 
Регистрация: 15.04.2012
Сообщений: 20
По умолчанию

Блин, новая проблема.
Я объявляю в классе Matrix поле Vector v();
Перед этим конечно пишу декларацию класса Vector перед определением Matrix.
Дальше в классе Matrix пишу оператор приведения типа:
Код:
operator Vector(void)const{ return v; };
компилятор пишет return type 'struct Vector' is incomplete, оно и понятно, ведь я использую имя Vector до его полного определения.
Скажите, как это обойти? Я читал, что надо объявлять указатель на еще неопределенный класс и все будет нормально, но я не могу понять как тогда переопределить оператор приведения типа, в интернете примеров найти не удалось.
sectors70 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
C++ проблема с конструктором базового класса halcyon Помощь студентам 7 09.05.2012 10:05
Создание базового класса ScrappyCoco Общие вопросы C/C++ 3 24.04.2012 15:51
Функция базового класса вызывает критическую ошибку при вызове для класса-потомка Archet Общие вопросы C/C++ 7 17.01.2012 20:17
Как обратиться к полям базового класса? Azartov Общие вопросы C/C++ 13 03.07.2011 20:32
Ошибка при присвоении объекту производного класса объекта базового класса с исп. явного приведения типов Lanx Помощь студентам 0 06.04.2011 20:24