0

I'm using complex numbers for learning design patterns. I'm currently using an abstract class:

namespace abstract{
    class complex{
        public:
            virtual ~complex() = 0;
            virtual double re() const = 0;
            // some other virtual function
    };    
};

namespace cartesian{
    class complex : public abstract::complex{
        public:
            complex(){}
            ~complex(){}
            double re() const override{return re_;};
            //... other functions
        private:
             double re_;
             double im_;

            // other
        
    };

};

namespace polar{
    class complex{
        /// polar complex numbers....
    };
};

I want to being able to write in the main:

cartesian::complex c(1,2);
polar::complex p(3,PI);
exponential::complex q = exp(c) + p;
print(q)

The thing is that I will have to write a lot of assignment operators with forward declarations for each class. So is there a way to make all representations of the complex class the same type, and having just different constructors? Something like pimpl with different pointers for each implementation or something with templates i don't know.

  • See `std::complex<>`. Maybe there is stuff in the header file that you can find useful (if there is a header *file*. – Thomas Matthews Nov 15 '22 at 01:35
  • This is a common problem with Buzzword Bingo: quickly getting bogged down in irrelevant details, and not really learning anything or improving any skills. A much better approach is to simply follow the organized curriculum in a good C++ textbook, to logically learn each C++ concept in a logical manner, one step at a time. – Sam Varshavchik Nov 15 '22 at 01:35
  • 1
    A polymorphic complex number class doesn't make any practical sense, it will be too heavy and too slow. – Evg Nov 15 '22 at 01:36
  • You can get around many assignment operators with converting constructors. Of course then you need to write the converting constructors... Either way you need to establish the rules. Patterns are cool when you look at a problem and realize within a few moments or minutes, "That's Visitor!" because you're off to the races. Otherwise, focus on finding a solution, and if you figure out that it fits a pattern later, maybe you refactor a bit to make your solution more pattern-y and maybe you don't. – user4581301 Nov 15 '22 at 01:39
  • Sidenote, not a fan of the way you did your namespace and class names. I'd rather have `namespace complex{ class cartesian_complex; class polar_complex; }` – Ranoiaetep Nov 15 '22 at 01:55
  • @Evg If i wanted something 100% optimized I would use std::complex<>, i'm trying to implement something fancy just for learning about design patterns. – Eric Cardozo Nov 15 '22 at 02:33
  • @Ranoiaetep Why not? is not very conventional but I think is more readable and intuitive to use... – Eric Cardozo Nov 15 '22 at 02:36
  • I understand that but why are you choosing something that is so inappropriate for such an implementation? There are so many other things to implement, Gang of Four book lists many practical examples. – Evg Nov 15 '22 at 02:36
  • 1
    *intuitive to use* - ADL will bite you. ;) – Evg Nov 15 '22 at 02:37
  • @Evg should I use a templated class instead? something like, complex, I hate underscores – Eric Cardozo Nov 15 '22 at 02:43
  • For learning purposes you have many different options depending on what you want to have in the end. If you want to use templates, for example, you can make a [CRTP](https://stackoverflow.com/questions/4173254/what-is-the-curiously-recurring-template-pattern-crtp) base class and then use derived classes for concrete implementations. Different representations won't have the same type, but you'll be able to write generic code that handles different representations more or less seamlessly. CRTP is widely used in numeric libraries. – Evg Nov 15 '22 at 02:51
  • Your sample code makes no use of polymorphism, so nothing in the GoF book is relevant to it. – n. m. could be an AI Nov 15 '22 at 10:13

1 Answers1

0

There is no common design pattern for this task.

And polymorphism is for me not a design pattern. It is a integral part of the C++ language.

And of course it is clear that everything is already existing in C++. So, you know std::complex already. I am not sure if you know about std::literals::complex_literals . With that you can write intuitive things like:

#include <iostream>
#include <complex>
 
int main()
{
    using namespace std::complex_literals;
    std::complex<double> c = 1.0 + 1i;
    std::cout << "abs" << c << " = " << std::abs(c) << '\n';
    std::complex<float> z = 3.0f + 4.0if;
    std::cout << "abs" << z << " = " << std::abs(z) << '\n';
}

Example taken from CPP reference


You could select one representation of a complex number and then convert all other forms into it. Then you can do all operations with one data type.

The only things that you would need to integrate then are more constructors and more assignment operators. But for that it would be better to use complex-literals.

So, my recommendation. Do not use polymorphism. It is too complex and too slow for this task.

Please consider.

For educational purposes, you may of course implement your solution. For this, use custom literals or a parser . . .

A M
  • 14,694
  • 5
  • 19
  • 44