Класс корни и степени. Помогите пожалуйста

Добрый день! Не могли бы мне помочь с прг. Проблема, как я понимаю в Wurzel& operator*(Wurzel& w) и исключения. Но не могу понять, что именно не так?
Класс корень и степень (матем)
Wurzel(1, 7) = 7 из 1

cout << Wurzel(1, 7) * Wurzel(0, 9) << endl; // вот это и должно быть исключением, так как корень = 0. 

try { 
cout << Wurzel а(1, 1) * d(3, 5) << endl; // а здесь все правильно 

} catch (...) 
{ 
cout << "Умножение не возможно!" << endl; 
}

Вот мой код классa Wurzel.h

#include <iostream>
#include <cmath>
namespace Programm {

    class Wurzel
    {
    public:
        double exp = 1.0;
        double wert = 1.0;

        Wurzel();
        Wurzel(double n, double a)
        {
            exp = n;
            wert = a;

            ResWurz();
        }

        Wurzel(Wurzel& w)
        {
            w.exp = 1.0;
            w.wert = 1.0;
            exp = w.exp;
            wert = w.wert;
            ResWurz();
        }

        double ResWurz()
        {
            if (wert > 0 && exp > 0)
            {
                return (double)pow(wert, 1 / exp);
            }
            else
            {
                throw 2;
            }
        }

        double Resultat()
        {
            return wert * exp;
        }

        Wurzel& operator*(Wurzel& w)
        {
            Wurzel res;
            if (w.wert > 0 && wert > 0 && w.exp > 0 && exp > 0)
            {
                if (exp == w.exp)
                {
                    res.wert = wert * w.wert;
                    res.exp = w.exp;
                    res.ResWurz();
                    return res;
                }
                if (wert == w.wert)
                {
                    res.wert = pow(wert, exp + w.exp);
                    res.exp = exp * w.exp;
                    res.ResWurz();
                    return res;
                }

                if (exp != w.exp && wert != w.wert)
                {
                    res.wert = (double)pow(wert, 1 / exp);
                    res.exp = (double)pow(w.wert, 1 / w.exp);

                    return res;
                }
            }

            else throw 123;
        }

        friend std::ostream& operator << (std::ostream& os, Wurzel& w)
        {
            os << w.Resultat();
            //os << w.ResWurz();

            return os;
        }

        ~Wurzel();
    };
}

rrg01, читаю твой код и возникает ощущение, что читаю бред. Кодобред. Ты сам-то понимаешь, что у тебя написано?

Для начала я бы тебе посоветовал написать подробные комментарии к твоему классу. Думаю, что в процессе ты многое изменишь. А потом, если проблема останется, можно и обсудить.

Это то что дано в задании, здесь к сожалению менять я ничего не имею право

#include <iostream> 
#include <conio.h>
#include "Wurzel.h"
using namespace std;
using Programm::Wurzel;

int main()
{
    Wurzel a;
    Wurzel b(3, 1);
    Wurzel c(1, 7);
    Wurzel d(3, 5);

    try{
        Wurzel e(7, 0); //7 из 0 ->Exception  
    }
    catch (...) { cout << "Степень не может быть равна 0!" << endl; }

    try {
        Wurzel f(5, -7); // -7 из 5 ->Exception  
    }
    catch (...) { cout << "Степень не может быть меньше 0!" << endl; }

    try {
        Wurzel g(-5, 7); // -5 из 7 ->Exception  
    }
    catch (...) { cout << "Корень не может быть меньше 0!" << endl; }

    //cout << a << " " << b << " " << c << " " << d << endl;

    // С этого момента прг не работает
    /*cout << Wurzel(1, 7) * Wurzel(0, 9) << endl;

    try {
    cout << a*d << endl;

    }   catch (...) { cout << "Умножение невозможно!" << endl; }

    try {
    cout << a*b << " " << a*c << " " << b*d << " " << d * Wurzel(7, 5) << endl;
    }   catch (...) {
    cout << "Ooops" << endl;
    }
    */
    _getch();
    return 0;
}

Такой вот должен быть вывод:

Степень не может быть равна 0!
Степень не может быть меньше 0!
Корень не может быть меньше 0!
 (1. из 1) (1. из 3) (1. из 1) (5. из 3) (1. из 0) 
Умножение невозможно!
 (1. из 3) (1. из 1) (5. из 729) (5. из 21)
#pragma once
#include <iostream>
#include <cmath>
namespace Programm {

    class Wurzel
    {
    public:
        double exp = 1.0; //степень
        double wert = 1.0; //корень

        Wurzel();
        Wurzel(double n, double a)
        {
            exp = n;
            wert = a;

            ResWurz();
        }

        Wurzel(Wurzel& w)
        {
            w.exp = 1.0;
            w.wert = 1.0;
            exp = w.exp;
            wert = w.wert;
            ResWurz();
        }

        double ResWurz()
        {
            if (wert > 0 && exp > 0)
            {
                return (double)pow(wert, 1 / exp); // подсчитывает корень из какой либо степени
            }
            else
            {
                throw 2;// если корень или степень меньше нулю, то обрабатывается исключение
            }
        }

        double Resultat()
        {
            return wert * exp;  // это я не знала как написать по другому if (exp != w.exp && wert != w.wert) данное. 
        }

        Wurzel& operator*(Wurzel& w) //умножение
        {
            Wurzel res;
            if (w.wert > 0 && wert > 0 && w.exp > 0 && exp > 0)
            {
               if (exp == w.exp) //если равны степени  𝑛√𝑎 ∗ 𝑛√𝑏  = 𝑛√𝑎 ∗ 𝑏 
                {
                    res.wert = wert * w.wert;
                    res.exp = w.exp;
                    res.ResWurz();
                    return res;
                }
     if (wert == w.wert)// если корни равны  𝑛√𝑎  ∗ 𝑚√𝑎  = 𝑛𝑚√𝑎 (в степени 𝑛+𝑚)
                {
                    res.wert = pow(wert, exp + w.exp);
                    res.exp = exp * w.exp;
                    res.ResWurz();
                    return res;
                }

    if (exp != w.exp && wert != w.wert) // если не то, не другое не равны
                {
                    res.wert = (double)pow(wert, 1 / exp);
                    res.exp = (double)pow(w.wert, 1 / w.exp);

                    return res;
                }
            }

            else throw 123; // если степень либо корень меньше 0
        }

        friend std::ostream& operator << (std::ostream& os, Wurzel& w)
        {
            os << w.Resultat();
            //os << w.ResWurz();

            return os;
        }

        ~Wurzel();
    };
}

Cranium, я начинающий программист, прошу строго не судить)

rrg01, позволь спросить, если ты пишешь, что «// С этого момента прг не работает», я делаю вывод, что ДО этого момента всё работает? Но как, Карл? Как? Как оно может работать, если оно не компилируется по причине отсутствия определений для конструктора и деструктора?

1>  main.cpp
1>main.obj : error LNK2019: unresolved external symbol "public: __thiscall Programm::Wurzel::Wurzel(void)" (??0Wurzel@Programm@@QAE@XZ) referenced in function _main
1>main.obj : error LNK2019: unresolved external symbol "public: __thiscall Programm::Wurzel::~Wurzel(void)" (??1Wurzel@Programm@@QAE@XZ) referenced in function _main
1>.\Debug\CodeTest-3.exe : fatal error LNK1120: 2 unresolved externals
========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========

это уже третий файл Wurzel.cpp, там конструктор и деструктор. А все методы и функции я выполняю в Wurzel.h. Из за этого все работает, и я внесла некоторые изменения, и проблема сейчас не в операторе * а в исключениях. Не могу понять почему, но компилятор все время выдает ошибку о том что исключение не обработано

Кстати с выводом тоже что-то напутано. Ты пишешь, что должно быть выведено:

(1. из 1) (1. из 3) (1. из 1) (5. из 3) (1. из 0)
Умножение невозможно!
(1. из 3) (1. из 1) (5. из 729) (5. из 21)

а из текста программы получается, что должно быть так:

(1 из 1) (1 из 3) (7 из 1) (5 из 3)
Умножение невозможно!
(1 из 3) (7 из 1) (5 из 729) (5 из 21)

А откуда появляется в первой строчке в конце (1. из 0) — я вообще не понял. По тексту программы эта строка вывода формируется оператором cout << a << " " << b << " " << c << " " << d << endl; — выводятся на печать четыре экземпляра класса, а последующий вывод должен начаться с новой строки.

Опаньки!.. Так ты и раздельную компиляцию умеешь? Так какого же чёрта ты определения методов в заголовочный файл понапихала?

rrg01, ты во многих местах наделала больших и маленьких ошибок. Мне, честно говоря, лениво во всё тыкать пальцем и комментировать. Ниже прилагаю код программы. Если я правильно понял задание, это должно работать именно так. Посмотри мой код, сравни со своим. Постарайся разобраться почему сделано именно так. Если будут вопросы — пиши.

main.cpp

#include <iostream> 

#include <conio.h>
#include "Wurzel.h"

using namespace std;

using Programm::Wurzel;

int main() {

    setlocale(LC_ALL, ".1251");     // отображение кириллицы (можно убрать, если не требуется)

    Wurzel a;
    Wurzel b(3, 1);
    Wurzel c(1, 7);
    Wurzel d(3, 5);

    try {
        Wurzel e(7, 0); //0 из 7 ->Exception  (!!!)
    }
    catch (...) { cout << "Степень не может быть равна 0!" << endl; }

    try {
        Wurzel f(5, -7); // -7 из 5 ->Exception  
    }
    catch (...) { cout << "Степень не может быть меньше 0!" << endl; }

    try {
        Wurzel g(-5, 7); // 7 из -5 ->Exception  (!!!)
    }
    catch (...) { cout << "Корень не может быть меньше 0!" << endl; }

    cout << a << " " << b << " " << c << " " << d << endl;

    //cout << Wurzel(1, 7) * Wurzel(0, 9) << endl;

    try {
        cout << a*d << endl;
    }
    catch (...) { cout << "Умножение невозможно!" << endl; }

    try {
        cout << a*b << " " << a*c << " " << b*d << " " << d * Wurzel(7, 5) << endl;
    }
    catch (...) {
        cout << "Ooops" << endl;
    }

    _getch();
    return 0;
}

Wurzel.h

#pragma once

#include <iostream>

namespace Programm {

    class Wurzel {

    public:
        Wurzel();
        Wurzel(double _wert, double _exp);
        Wurzel(const Wurzel& w);

        void validate() const;                  // проверка значений членов класса на допустимость
        Wurzel operator * (const Wurzel& w);    // умножение

        friend std::ostream& operator << (std::ostream& os, const Wurzel& w);

    private:
        double exp;             // степень
        double wert;            // подкоренное выражение
    };
}

Wurzel.cpp

#include "Wurzel.h"

namespace Programm {

    Wurzel::Wurzel() : exp(1.0), wert(1.0) {}

    Wurzel::Wurzel(double _wert, double _exp) {
        exp = _exp;
        wert = _wert;

        validate();
    }

    Wurzel::Wurzel(const Wurzel & w) {
        exp = w.exp;
        wert = w.wert;

        validate();
    }

    inline void Wurzel::validate() const {
        if (wert < 0 || exp <= 0) {
            // если подкоренное выражение отрицательное или 
            // степень отрицательная или 0, то возбуждается исключение
            throw 1;  
        }
    }

    Wurzel Wurzel::operator*(const Wurzel & w) {
        Wurzel res;
        if (exp == w.exp) //если равны степени, 
        {
            // результат = корню той же степени из произведения подкоренных выражений  
            res.wert = wert * w.wert;
            res.exp = w.exp;
            res.validate();
            return res;
        }
        if (wert == w.wert) // если подкоренные выражения равны, 
        {
            // результат = корню степени exp1 + exp2 из подкоренного выражения в степени exp1 * exp2
            res.wert = pow(wert, exp + w.exp);
            res.exp = exp * w.exp;
            res.validate();
            return res;
        }

        throw 2;  // умножение невозможно - возбуждается исключение
    }

    std::ostream & operator<<(std::ostream & os, const Wurzel & w) {
        return os << '(' << w.exp << " из " << w.wert << ')';
    }

}

Извините, но у меня все же есть пару вопросов.
Почему private:
double exp;
double wert;
в конце? это без разницы?
и еще один момент, в коде у вас под комментарием остался не выведенный cout;

//cout << Wurzel(1, 7) * Wurzel(0, 9) << endl;

Это должно должно быть исключением, но в рамки try не входит. И естественно компилятор выдает ошибку, не обработанное исключение.
Но задание изменить не возможно.

Где в объявлении класса располагается секция private — без разницы. Рекомендуют в конце. Из тех соображений, что когда человек читает объявление класса, основное внимание уделяется открытым методам и членам.

и еще один момент, в коде у вас под комментарием остался не выведенный cout;

//cout << Wurzel(1, 7) * Wurzel(0, 9) << endl;

Это должно должно быть исключением, но в рамки try не входит. И естественно компилятор выдает ошибку, не обработанное исключение.

Этот ребус я кажется тоже разгадал. Это, фактически, — умножение на 0. Поэтому исключения здесь не будет. Но надо этот «особый случай» отработать в перегруженном операторе умножения:

    Wurzel Wurzel::operator*(const Wurzel & w) {
        Wurzel res;
        if (w.wert == 0) { // умножение на 0
            // второй операнд равен 0, если его подкоренное выражение равно 0
            return Wurzel(0, 1);    // возвращаем 0
        }

        if (exp == w.exp) //если равны степени, 
        {
            // результат = корню той же степени из произведения подкоренных выражений  
            res.wert = wert * w.wert;
            res.exp = w.exp;
            res.validate();
            return res;
        }
        if (wert == w.wert) // если подкоренные выражения равны, 
        {
            // результат = корню степени exp1 + exp2 из подкоренного выражения в степени exp1 * exp2
            res.wert = pow(wert, exp + w.exp);
            res.exp = exp * w.exp;
            res.validate();
            return res;
        }

        throw 2;  // умножение невозможно - возбуждается исключение
    }

Спасибо большое за помощь!
Можно к вам обратиться еще по одному вопросы, но уже другое задание.
Не могу понять, как работать с enum в классах(как создать конструктор тд тп с enum)

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

Не могу понять, как работать с enum в классах(как создать конструктор тд тп с enum)

Вопрос(ы) сформулируй поконкретнее. Пока непонятно с чем у тебя проблемы.

PS. Когда постишь исходный код, оформляй по здешним правилам разметки (написаны над окном ввода поста; лучше оформлять «вручную»). И проверяй что получается кнопкой Предпросмотр.

Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.

Ответить

Вы можете использовать разметку markdown для оформления комментариев и постов. Используйте функцию предпросмотра для проверки корректности разметки.

Пожалуйста, оформляйте исходный код в соответствии с правилами разметки. Для того, чтобы вставить код в комментарий, скопируйте его в текстовое поле ниже, после чего выделите то, что скопировали и нажмите кнопку «код» в панели инструментов. Иначе ваш код может принять нечитаемый вид.

Либо производите оформление кода вручную, следующим образом:

``` #include <iostream> using namespace std; int main() { // ... } ```

Предпросмотр сообщения

Ваше сообщение пусто.