1. C++ / Говнокод #22806

    −13

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    using System;
    
    namespace TestIssue
    {
    	interface Iface1
    	{
    		int _get(int i);
    	}
    
    	interface Iface2
    	{
    		int _get(int i);
    	}
    
    	class S : Iface1, Iface2
    	{
    		int Iface1._get(int i) { return i; }
    		int Iface2._get(int i) { return i * 2; }
    	}
    
    	class Program
    	{
    		public static int Main ()
    		{
    			S s = new S();
    			var f1 = (Iface1)s;
    			var f2 = (Iface2)s;
    			Console.WriteLine(f1._get(10));
    			Console.WriteLine(f2._get(20));
    			return 0;
    		}
    	}
    }

    Задача:

    Имеем код на С#. Нужно написать тоже самое только на С++ (я имею ввиду ближайшие варианты по имплементации явных интерфейсов.

    Запостил: ASD_77, 13 Апреля 2017

    Комментарии (31) RSS


    • struct Iface1 {
      int get(int val) { return val; }
      };

      struct Iface2 {
      int get(int val) { return val*2; }
      };

      struct S : Iface1, Iface2 {};

      int main() {
      S s;
      std::cout << ((Iface1&)s).get(10) << std::endl;
      std::cout << ((Iface2&)s).get(20) << std::endl;
      }
      Ответить
    • Iface подразумевают что надо юзать виртуальные функции

      типа такого

      struct Iface1 {
      virtual int get(int val) = 0
      };
      
      struct Iface2 {
      virtual int get(int val) = 0
      };
      
      struct S : Iface1, Iface2 {
      int get(int val) { return val; }
      int get(int val) { return val*2; }
      };
      
      int main() {
      S s;
      std::cout << ((Iface1&)s).get(10) << std::endl;
      std::cout << ((Iface2&)s).get(20) << std::endl;
      }
      Ответить
      • нет у тебя ни соображалки, ни чувства юмора.

        struct Iface1 {
            virtual int get(int val) = 0;
        };
        
        struct Iface2 {
            virtual int get(int val) = 0;
        };
        
        struct S {
            operator Iface1 &() { return _impl1; }
            operator Iface2 &() { return _impl2; }
        
        private:
            struct Impl1 : Iface1 {
                int get(int val) { return val; }
            } _impl1;
            struct Impl2 : Iface2 {
                int get(int val) { return val*2; }
            } _impl2;
        };
        
        int main() {
            S s;
            std::cout << ((Iface1&)s).get(10) << std::endl;
            std::cout << ((Iface2&)s).get(20) << std::endl;
        }
        Ответить
        • ага прикольно. надо запомнить

          но чувствую что где-то кидают

          вот мой вариант

          #include <iostream>
          
          class Iface1
          {
          public:
          	virtual int get(int, Iface1* = nullptr) = 0;
          };
          
          class Iface2
          {
          public:
          	virtual int get(int, Iface2* = nullptr) = 0;
          };
          
          class S: public Iface1, public Iface2
          {
          public:
          	int get(int i, Iface1* = nullptr) override { return i; };
          	int get(int i, Iface2* = nullptr) override { return i * 2; };
          };
          
          int main (int argc, char **argv)
          {
            S s;
          
            auto f1 = (Iface1*)&s;
            auto f2 = (Iface2*)&s;
          
            std::cout << "HelloWorld " << f1->get(10) << " " << f2->get(20) << std::endl;
            return 0;
          }
          Ответить
          • Ты, по сути, переименовал функции в интерфейсах. Незачёт.
            Ответить
            • я это называю - придать добавить распозноваемости :)
              Ответить
          • Глупая идея: а какие более характерные (и различные) имена функциям давать не пробовал?

            Одно дело когда кунпилер догадаться не можешь что ты перекрываешь/вызываешь - но куда намного хуже что девелоперы тоже ни хера догадатся не могут.

            Я как то работал с либой там было 4-5 контейнеров. В каждом была пара дюжин insert()/delete()/enqueue()/dequeue() методов с различными аргументами. Самая популярная ошибка на протяжении жизни проета была что вызывался неправильный метод. Самая заябучая неприятность: когда вываливается список доступных имен, в нем сидит две дюжины методов с тем же именем - и все со слегка различными аргументами. Править это было мрак.
            Ответить
            • мне это надо только для runtime -а так что никто этот код особо видеть не будет
              Ответить
              • я сам подобное как Antervis решал. я делал почти только так же - только вместо операторов, я делал явные методы AsIntf1() & AsIntf2().

                и самое главное: вместо "iface" я пишу "intf".
                Ответить
                • > самое главное: вместо "iface" я пишу "intf"

                  это большое отличие, очень хорошее
                  Ответить
                  • Написал бы if, но конпелятору почему-то не нравится...
                    Ответить
                • как-то раз увидел в коде переменную со страшным именем iface. Думаю - "а почему бы не interface?". Поменял. Не собралось. Оказалось, что в винде это макрос для какого-то COM-говна.

                  а вообще, ICamelCase Ftw
                  Ответить
        • плюсанул.
          Ответить
    • можно еще через промежуточные реализации:
      struct Iface1 {
          virtual int get(int val) = 0;
      };
      
      struct Iface2 {
          virtual int get(int val) = 0;
      };
      
      struct Impl1 : Iface1 {
          int get(int val) { return val; }
      };
      struct Impl2 : Iface2 {
          int get(int val) { return val*2; }
      };
      
      struct S : Impl1, Impl2 {};
      Ответить
      • Так общий стейт не доступен. Если уж использовать вспомогательные структуры, то лучше как-то так:
        struct Iface1 {
            virtual int get(int val) = 0;
        };
        
        struct Iface2 {
            virtual int get(int val) = 0;
        };
        
        struct Impl1 : Iface1 {
            int get(int val) override { return Iface1_get(val); }
            virtual int Iface1_get(int val) = 0;
        };
        struct Impl2 : Iface2 {
            int get(int val) override { return Iface2_get(val); }
            virtual int Iface2_get(int val) = 0;
        };
        
        struct S : Impl1, Impl2 {
          int Iface1_get(int val) override { return val; }
          int Iface2_get(int val) override { return val * 2; }
        };
        Ответить
    • Наверняка уже бьіло, но мне зачесалось тоже написать: https://wandbox.org/permlink/k5nM6yXwkyOeiRvE

      class Iface1 {
      public:
          int get(int i) { return getForInterface1(i); }
          
      private:
          virtual int getForInterface1(int i) = 0;
      };
      
      class Iface2 {
      public:
          int get(int i) { return getForInterface2(i); }
          
      private:
          virtual int getForInterface2(int i) = 0;
      };
      
      class S : public Iface1, public Iface2 {
      public:
          // fuck ambiguity
          int get(int) = delete;
          
      private:
          int getForInterface1(int i) override { return i; }
          int getForInterface2(int i) override { return i * 2; }
      };
      
      int main()
      {
          S s;
          auto &f1 = static_cast<Iface1&>(s);
          auto &f2 = static_cast<Iface2&>(s);
          std::cout << f1.get(10) << std::endl;
          std::cout << f2.get(20) << std::endl;
          
          return 0;
      }
      Ответить
    • всем спасибо - достаточно позновательно и главное практично :)
      Ответить
    • #include <cstdlib>
      #include <fstream>
      
      const char text[] =
      
      "using System;\n"
      "\n"
      "namespace TestIssue\n"
      "{\n"
      "	interface Iface1\n"
      "	{\n"
      "		int _get(int i);\n"
      "	}\n"
      "\n"
      "	interface Iface2\n"
      "	{\n"
      "		int _get(int i);\n"
      "	}\n"
      "\n"
      "	class S : Iface1, Iface2\n"
      "	{\n"
      "		int Iface1._get(int i) { return i; }\n"
      "		int Iface2._get(int i) { return i * 2; }\n"
      "	}\n"
      "\n"
      "	class Program\n"
      "	{\n"
      "		public static int Main ()\n"
      "		{\n"
      "			S s = new S();\n"
      "			var f1 = (Iface1)s;\n"
      "			var f2 = (Iface2)s;\n"
      "			Console.WriteLine(f1._get(10));\n"
      "			Console.WriteLine(f2._get(20));\n"
      "			return 0;\n"
      "		}\n"
      "	}\n"
      "}";
      
      
      
      int main(int c, char * v[]) {
      	using namespace std;
      	ofstream("kokoko.cs", ofstream::out | ofstream::text) << text;
      	system("csc.exe /out:kudah.exe kokoko.cs");
      	system("kudah.exe");
      }
      Ответить
    • #include <iostream>
      
      struct IFace1 {
         virtual int get( int ) = 0;
      };
      
      struct IFace2 {
         virtual int get( int ) = 0;
      };
      
      struct S: IFace1, IFace2 {
         int IFace1::get( int x ) {
            return x;
         }
      
         int IFace2::get( int x ) {
            return x * x;
         }
      };
      
      int main() {
         S s;
      
         IFace1 &f1 = s;
         IFace2 &f2 = s;
      
      	std::cout << f1.get( 2 ) << ' ' << f2.get( 2 ) << std::endl;
      
      	return 0;
      }
      Ответить
      • А есть видео где это компилируют?
        Ответить
        • 15 студия делает это. gcc 5.3.0 - нет.
          Ответить
          • я всегда говорил и буду говорить: майкрософтам проще создать новый язык, чем выдержать стандарт существующего
            Ответить
            • Да ладно тебе, как будто -std=gnu++* никогда не видел
              Ответить
              • Видел. Сам не пользуюсь и другим не советую. Разница в том, что gnu расширения приходят из си и как правило потом попадают в стандарт, а студийные нужны разве что самим майкам
                Ответить

    Добавить комментарий