O nadużywaniu C++/CLI

O nadużywaniu C++/CLI
RE
Moderator
  • Rejestracja:około 18 lat
  • Ostatnio:12 miesięcy
19

@Azarien napisał dzisiaj, że Nie ma powodu, by C++/CLI musiało być tylko do „portowania bibliotek” poza tym, że wielu tak uważa. Chciałbym poruszyć ten wątek, a że w tamtym w gruncie rzeczy mowa o innym języku to założyłem nowy.

Ostatnimi czasy widać w Polsce zwiększające się zainteresowanie językiem C++/CLI. Jak dla mnie, wynika to z niczego innego jak próbą pójścia na skróty w nauce czystego C++. Wiadomo: czytelniejsza biblioteka standardowa, a klepanie interfejsu użytkownika w Visual Studio nigdy nie było prostsze. Koniec końców najczęściej jest taki, że przychodzi człowiek na forum, bo nie może sobie poradzić ze składnią tego tworu i okazuje się, że nie poznał ani C++, ani .NET.

Także apeluję do młodszych (stażem, bo sam młody wiekiem jestem) programistów: nie zabierajcie się za C++/CLI, jeżeli chcecie się nauczyć C++ oraz nie zabierajcie się za C++/CLI, jeżeli chcecie nauczyć się .NET.

W pierwszym przypadku uczcie się po prostu C++. Po dogłębnym przestudiowaniu wcale niedużej biblioteki standardowej ze zdziwieniem stwierdzicie na koniec, że i tak zaoszczędzi wam kupę czasu, bo przykładowo nie trzeba już korzystać z ręcznie klepanych pętli czy mieszać gdzieś w kod bibliotekę C do operowania na napisach, bo nigdy wcześniej nie spodziewaliście się, że nagłówek <algorithm>, iteratory, insertery, i/o stringstreamy mogą być tak proste i przydatne. Można pójść dalej i poznać nowe (w standardzie) inteligentne wskaźniki i na zawsze zrezygnować z ręcznego zarządzania pamięci.

Jeżeli z kolei podoba wam się przeciąganie kontrolek na formę w Visual Studio i nie macie odgórnego wymogu (ze szkoły, uczelni) na naukę C++ to bezwzględnie piszcie od razu w C#. O ile na samiutkim początku może zbyt dużej różnicy nie ma, bo kompilator i tak wygeneruje kod za was, to już za chwilę zababracie się zupełnie w C++/CLI. Nie jest to wcale dziwne, bo nie dość, że C++ jest językiem skomplikowanym to dołączenie do niego zawiłości CLR z niedoskonałą (w porównaniu do C#, gdzie twórcy języka mogli zaprojektować go od zupełnych podstaw) składnią prowadzi do katastrofy. A idzie nam jeszcze Windows 8, WinRT i kolejna odmiana C++, czyli C++/CX z podobnymi, ale znów innymi i prowadzącymi do kolejnych nieporozumień rozszerzeniami.

Spójrzcie z resztą na tą bardzo prostą klasę, którą napisałem jakiś czas temu w C#.

Kopiuj
namespace Rev.PhotoAlbum.Application.Modules
{
    using Autofac;

    using NHibernate;
    using NHibernate.Cfg;

    using Rev.PhotoAlbum.Model.Configuration;
    using Rev.PhotoAlbum.Model.Repositories;

    public class DataAccessModule : Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            var configuration = Configurator.BuildConfiguration();
            var sessionFactory = Configurator.BuildSessionFactory(configuration);

            RegisterComponents(builder, configuration, sessionFactory);
        }

        private void RegisterComponents(ContainerBuilder builder, Configuration configuration, ISessionFactory sessionFactory)
        {
            builder.RegisterInstance(configuration).As<Configuration>().SingleInstance();
            builder.RegisterInstance(sessionFactory).As<ISessionFactory>().SingleInstance();
            builder.Register(x => x.Resolve<ISessionFactory>().OpenSession()).As<ISession>().InstancePerLifetimeScope();

            builder.RegisterAssemblyTypes(typeof(IRepository<>).Assembly)
                .Where(t => t.IsClosedTypeOf(typeof(Repository<,>)))
                .AsClosedTypesOf(typeof(IRepository<>));
        }
    }
}

Nie ma co prawda w kodzie komentarzy, ale dzięki odpowiedniej konstrukcji frameworków, z których korzystam kod ten można.. po prostu przeczytać - ciągiem. Układają się z tego zdania i na pierwszy rzut oka można się domyślić co się dzieje - chodzi mi zwłaszcza o metodę RegisterComponents. Jeżeli ktoś nigdy z AutoFaca nie korzystał, a ma minimalną wiedzę z teorii na temat kontenerów IoC mógłby własny kod napisać po jedno, dwu-krotnym przeczytaniu mojego.

A teraz ten sam kod w C++/CLI.
Najpierw oczywiście plik nagłówkowy, jako sumienni programiści C++ nie wrzucamy wszystkiego do jednego pliku.

Kopiuj
#pragma once

namespace Rev
{
	namespace PhotoAlbum
	{
		namespace Application
		{
			namespace Modules
			{
				ref class DataAccessModule : public Autofac::Module
				{
				private:
					void RegisterComponents(Autofac::ContainerBuilder^ builder, NHibernate::Cfg::Configuration^ configuration, NHibernate::ISessionFactory^ sessionFactory);
				protected:
					virtual void Load(Autofac::ContainerBuilder^ builder) override;
				};
			}
		}
	}
}

Ah, no tak. C++ nie obsługuje zagnieżdżonych przestrzeń nazw w jednej instrukcji, musimy rozbić je na kilka. Tutaj pedantycznie trzymam się formatowania, które sobie przyjąłem, możemy zawsze wrzucić wszystkie namespace'y do jednej linijki albo - jak polecają w internecie - stworzyć sobie makro. A jak.
Rozciągnął się kod niesamowicie, no, ale przecież mamy na uwadze zasadę nieużywania using namespace w plikach nagłówkowych, żeby nie potworzyć żadnych konfliktów nazw w plikach, gdzie będziemy nasz plik nagłówkowy dołączać.

Kopiuj
using namespace Rev::PhotoAlbum::Application::Modules;

using namespace Autofac;

using namespace NHibernate;
using namespace NHibernate::Cfg;

using namespace Rev::PhotoAlbum::Model::Configuration;
using namespace Rev::PhotoAlbum::Model::Repositories;

void DataAccessModule::Load(ContainerBuilder^ builder)
{
	auto configuration = Configurator::BuildConfiguration();
	auto sessionFactory = Configurator::BuildSessionFactory(configuration);

	RegisterComponents(builder, configuration, sessionFactory);
}

ISession^ ISessionResolve(IComponentContext^ context)
{
	return ResolutionExtensions::Resolve<ISessionFactory^>(context)->OpenSession();
}

bool IRepositoryWhereCondition(System::Type^ type)
{
	return TypeExtensions::IsClosedTypeOf(type, Repository::typeid);
}

void DataAccessModule::RegisterComponents(ContainerBuilder^ builder, Configuration^ configuration, ISessionFactory^ sessionFactory)
{
	RegistrationExtensions::RegisterInstance(builder, configuration)->As<Configuration^>()->SingleInstance();
	RegistrationExtensions::RegisterInstance(builder, sessionFactory)->As<ISessionFactory^>()->SingleInstance();

	RegistrationExtensions::Register<ISession^>(builder, gcnew System::Func<IComponentContext^, ISession^>(&ISessionResolve))->As<ISession^>()->InstancePerLifetimeScope();

	RegistrationExtensions::AsClosedTypesOf(RegistrationExtensions::Where(RegistrationExtensions::RegisterAssemblyTypes(builder, IRepository::typeid->Assembly),
		gcnew System::Func<System::Type^, bool>(&IRepositoryWhereCondition)), IRepository::typeid);
}

Chciałbym zwłaszcza zwrócić na końcówkę metody RegisterComponents. Konia z rzędem temu, kto rozszyfruje co się tutaj dzieje. Niestety (albo stety) bardzo wiele frameworków, które ułatwiają (taa) pisanie w .NET korzystają z metod rozszerzających (z resztą zdaje się, że bardzo dobrze, zgodnie z zasadą open/closed). Z jakiś powodów najzwyczajniej nie są one składniowo obsługiwane w C++/CLI i trzeba wywoływać je ręcznie, z klasy, w której są zdefiniowane i przekazywać ręcznie obiekt. Bez tracenia dodatkowego czasu na znalezienie chociażby nazwy tej klasy się nie obejdzie. Kolejna rzecz to lambdy, które w C# niesamowicie ułatwiają sprawę, a w C++/CLI powodują, że musimy je wydzielić do zewnętrznej metody. Lambdy z C++11 nawet w Visual Studio 11 nie są z nimi kompatybilne. No trudno.
Ktoś mógłby powiedzieć, że klepanie nawet takiego kodu z IntelliSense nie będzie trudne. Nawet dodali do niego obsługę C++/CLI. Bardziej przykra sprawa jest taka, że na co trzeciej bardziej rozbudowanej linijce z typami generycznymi po prostu się wykłada i zaczyna krzyczeć o błędach. Których de facto nie ma, bo kod się kompiluje i działa.

Wykorzystanie w C#:

Kopiuj
var builder = new ContainerBuilder();
builder.RegisterModule<Modules.DataAccessModule>();
var container = builder.Build();
var repository = container.Resolve<IRepository<Person>>();

I C++/CLI:

Kopiuj
auto builder = gcnew ContainerBuilder();
RegistrationExtensions::RegisterModule<Modules::DataAccessModule^>(builder);
auto container = builder->Build(Builder::ContainerBuildOptions::Default);
auto repository = ResolutionExtensions::Resolve<IRepository<Person^>^>(container);

Nie domyślił się wartości domyślnej parametru, a IntelliSense rzucił malowniczy błąd w ostatniej linii o tym, że wywołanie pasuje do wielu przeładowań oraz jednocześnie ma za mało parametrów.

Nie mówię, że pisanie w C++/CLI nie ma w ogóle sensu. Ma, ale są to naprawdę marginalne zastosowania, gdy nie wystarcza nam P/Invoke i interop w C#. Ja jeszcze nigdy nie musiałem go naprawdę użyć. Wy pewnie też nie.

SZ
To nie zawsze jest tak fajnie. Większość ludzi poznaje programowanie na studiach (bądź w TI - ale tu jest sporo godzin w cyklu kształcenia na PSiO i program nie jest zbyt rozbudowany. Jestem akurat świadkiem tego jak na Politechnice Poznańskiej wyglądają zajęcia z <i>programowani</i>. I semestr fizyk techniczna, w sześciu 90 minutowych wykładam omówiona całość składni C++ (włączywszy takie szczegóły jak wskaźniki na funkcje, wskaźniki na składowe, sporo funkcji z <code>cstring, stdio, stdlib</code>. No i super bo ludzie nic nie wiedzą, nic a wykładowca zadowolony.
SZ
Na ćwiczeniach... prowadzący pisze kod, rzuca na ekran. 5 min na przepisanie i "to już wiecie z grubsza o co tutaj chodzi". Tyle w I sem. Na drugim roku, fizyka komputerowa. Po takich wątpliwych postawach C++, od razu rzut na C++/CLI. Gierki typu obsługa zdarzenia i poruszanie piłeczką aby trafić w uciekającą w losowe miejsca na ekranie bramkę. Metoda uczenia? "Otwieracie nowy projekt i na moim komputerze macie plik, z niego kopiujecie, jeśli działa to idziemy dalej". Jeśli nie działa to "szukacie błędów" a jak ludzie mają ich szukać jak nie rozumieją większości kodu...
maszynaz
  • Rejestracja:ponad 17 lat
  • Ostatnio:około 12 lat
1

co to znaczy "portowanie bibliotek"?


"Wszystko co może być wynalezione, zostało wynalezione"
Charless H. Duell - komisarz urzędu patentowego U.S., 1899
PO
  • Rejestracja:prawie 19 lat
  • Ostatnio:prawie 10 lat
1

Pewnie chodziło o wrappery.

A tak w temacie, to mam też wrażenie, że początkujący często nieświadomie piszą w C++/CLI. W końcu nazwa podobna:).

Wibowit
  • Rejestracja:prawie 20 lat
  • Ostatnio:20 minut
0

Co się dziwić, znaczna część programistów (edit: tzn tych bardzo początkujących) C# myśli, że (C#) to jest jakiś następca C++.


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
edytowany 2x, ostatnio: Wibowit
msm
Administrator
  • Rejestracja:prawie 16 lat
  • Ostatnio:5 miesięcy
1

@Rev - myślę że problem z twoją argumentacją wynika z tego że próbujesz patrzeć na C++/CLI jak na C# z inną składnią. Chociażby AutoFac którego przykład podałeś - był on projektowany specjalnie pod C#. To że w ogóle działa pod C++/CLI to wynik zgodności języków zarządzanych a nie jakieś celowe zagranie.

Równie kiepskie podejście do C++/CLI to patrzenie na niego jako na C++ z dodatkową biblioteką standardową. Momentalnie zaczynają pojawiać się problemy z łączeniem zarządzanych i niezarządzanych fragmentów.

somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:około 9 godzin
  • Lokalizacja:Wrocław
4
Wibowit napisał(a)

Co się dziwić, znaczna część programistów C# myśli, że (C#) to jest jakiś następca C++.

Tja, a programiści JavaScript myślą, że to jakiś następca Javy.
Jeśli ktoś tak uważa, to programistą C# nie jest i raczej nie będzie.

Tezcatlipoca napisał(a)

@Rev - myślę że problem z twoją argumentacją wynika z tego że próbujesz patrzeć na C++/CLI jak na C# z inną składnią.

Nie zauważyłem, żeby @Rev miał problem z argumentacją, to chyba Ty masz jakiś problem z jego argumentami. To nie on patrzy na C++/CLI w ten sposób, lecz ci, którzy próbują go tak używać i na siłę robić z niego język ogólnego przeznaczenia.

Jakieś dziecko przeczyta w internecie, że Prawdziwi Profesjonalni Programiści piszą w C++, ściąga VC++, tworzy projekt i zaczyna się magia, dzięki której w 5 minut robi GUI jak w prawdziwym programie, więc myśli, że dalej będzie już z górki. Dzieciak nie wie, że to nie jest C++, dzieciak nie wie o co chodzi z tym CLI, nie wie, co to .NET - nie wie nic, ale myśli, że uczy się Jedynego Słusznego Języka Do Pisania Gier. I stąd wynikają wspomniane przez Ciebie problemy z łączeniem zarządzanych i niezarządzanych fragmentów kodu.

msm
Administrator
  • Rejestracja:prawie 16 lat
  • Ostatnio:5 miesięcy
2
somekind napisał(a)
Tezcatlipoca napisał(a)

@Rev - myślę że problem z twoją argumentacją wynika z tego że próbujesz patrzeć na C++/CLI jak na C# z inną składnią.

Nie zauważyłem, żeby @Rev miał problem z argumentacją, to chyba Ty masz jakiś problem z jego argumentami. To nie on patrzy na C++/CLI w ten sposób, lecz ci, którzy próbują go tak używać i na siłę robić z niego język ogólnego przeznaczenia.

Ja tylko zauważam że porównanie C++/CLI i C# na podstawie przepisywania kodu z tego drugiego do pierwszego jest trochę nieodpowiednie.
Te języki mają po prostu zupełnie inne zastosowania i to jest chyba dla wszystkich oczywiste?

edytowany 2x, ostatnio: msm
RE
Moderator
  • Rejestracja:około 18 lat
  • Ostatnio:12 miesięcy
2

Te języki mają po prostu zupełnie inne zastosowania i to jest chyba dla wszystkich oczywiste?

W całym moim wywodzie chodzi właśnie o to, żeby to pokazać. Gdybyś czytał wszystkie wątki w dziale .NET i C++ to wiedziałbyś, że jest to sprawa wielce nieoczywista dla niezliczonej ilości osób.
A ten nieudany kod w C++/CLI, który zaprezentowałem tylko to potwierdza. Ten przykład miał pokazać, że pisanie kodu aplikacji biznesowych w środowisku .NET w C++/CLI jest bez sensu, gdy mamy C#.

ZJ
  • Rejestracja:około 14 lat
  • Ostatnio:około 12 lat
0

Zawsze mi się wydawało, że głównym celem C++/CLI jest ułatwienie przeniesienia sporych aplikacji na platformę .NET bez potrzeby przepisywania całego kodu do C#, tylko pisząc w nim nowe elementy.

somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:około 9 godzin
  • Lokalizacja:Wrocław
1
Tezcatlipoca napisał(a)

Ja tylko zauważam że porównanie C++/CLI i C# na podstawie przepisywania kodu z tego drugiego do pierwszego jest trochę nieodpowiednie.

A na jakiej innej zasadzie można porównać przydatność języków do danego zastosowania, jeśli nie poprzez zwięzłość i czytelność kodu?

Wibowit
  • Rejestracja:prawie 20 lat
  • Ostatnio:20 minut
0
somekind napisał(a)
Wibowit napisał(a)

Co się dziwić, znaczna część programistów C# myśli, że (C#) to jest jakiś następca C++.

Tja, a programiści JavaScript myślą, że to jakiś następca Javy.
Jeśli ktoś tak uważa, to programistą C# nie jest i raczej nie będzie.

Przecież na tym forum niejeden początkujący programista C# tak myśli...

A na jakiej innej zasadzie można porównać przydatność języków do danego zastosowania, jeśli nie poprzez zwięzłość i czytelność kodu?

Haskell jest zwięzły, czytelny, a obecne wersje kompilatorów tworzą dość wydajny kod.

Tak mogą myśleć jacyś newbie i totalni laicy, a nie ktoś, kto ma jako takie pojęcie o tych językach. :)

No napisałem początkujący (czyli newbie). Zbieżność nazw C++ i C# jest dla nich argumentem za tym, żeby po C++ wybrać C#, a nie np Javę, Scalę, Ruby, Pythona, etc Podobnie w drugą stronę, był tu przypadek typa, który myślał, że C++ to taki inny C# i wrzucał public i private przed każdą deklaracją.

stfu:
Zgoda, zapomniałem dopisać początkujących.


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
edytowany 2x, ostatnio: Wibowit
somekind
Tak mogą myśleć jacyś newbie i totalni laicy, a nie ktoś, kto ma jako takie pojęcie o tych językach. :)
ST
Znaczna część programistów != niejeden początkujący programista (na tym forum)
tubiz
Typowe zachowanie piekarza który wstał rano z wyra lewą nogą i głośno powiedział: od dziś będę programistą. Nie zmienia to jednak faktu iż to nie jego wina że na rynku programowania mamy burdel. C,C#,C++,VC#,VC++... Do tego C99, C11 i masa innych. ANSI trochę przegina.
Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 14 godzin
2

Podany przykład jest wybitnie tendencyjny, bo opiera się na tym, że C++/CLI nie ma extension methods. Gdyby Microsoft w końcu zaimplementował rozszerzenia pod C++/CLI, ten argument by znikł.

Można również pokazać argument odwrotny, jakiegoś kodu używającego biblioteki napisanej w C++, najlepiej obiektowo z szablonami, i jej użycie spod C++/CLI i spod C#.

Ubolewam jednak, że M$ od kilku wersji kompletnie olewa C++/CLI tłumacząc się „brakiem zasobów”, w rezultacie czego język stanął na poziomie .Net 2.0. Z tego powodu użycie konstrukcji specyficznych dla nowszych wersji frameworka jest skomplikowane albo niemożliwe.
To nie jest wina języka, ale mizernego jego rozwoju.

edytowany 1x, ostatnio: Azarien
OT
  • Rejestracja:około 20 lat
  • Ostatnio:ponad 11 lat
3

Pytanie do czego przydaje się w ogóle C++/CLI? Bo poza celowym łączeniem kodu zarządzanego i niezarządzanego jakoś zastosowań nie widzę. Sam bym myślał o użyciu C++/CLI tylko do:

  • napisania biblioteki dll, która będzie wrapperem importującym wiele funkcji natywnych lub klas z natywnej bibloteki .dll. Potem ten wrapper używany w projekcie w C# jako normalne assembly. O ile mi wiadomo, jeśli niezarządzana biblioteka dll eksportuje bezpośrednio klasy to użycie jej w C# bezpośrednio może okazać się niemożliwe
  • uzyskania sytuacji odwrotnej: mam projekt w natywnym C++, np mfc albo C++ Builder i zachciało mi się użyć funkcjonalności z .net. Robię wrappera, który eksportuje niezarządzane funkcje możliwe do użycia w projekcie w C++ niezarządzanym.

Ale po jaką cholerę pisać całe aplikacje w C++/CLI - tego nie rozumiem. Zresztą, pomijając to wszystko co zostało już powiedziane, jedyne co osiągniemy to aplikacja w WinForms z pewnymi ograniczeniami, nie ma wpf, nie ma webserwisów itd itp.

Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 14 godzin
1

napisania biblioteki dll, która będzie wrapperem importującym wiele funkcji natywnych lub klas z natywnej bibloteki .dll
Biblioteka może być wielka, specjalistyczna, używać konstrukcji typowych dla C++. Samo napisanie wrappera może być zbyt dużym zadaniem, większym niż zaciśnięcie zębów i napisanie GUI w C++/CLI.

C++/CLI jest dla mnie najbardziej naturalnym wyborem jeśli mam na szybko napisać aplikację GUI, pod Windows, w C++.
Prawie w C++, powiedzmy.

Jeśli jednak nie ma argumentów przemawiających za C++, wybieram C# naturalnie.

edytowany 1x, ostatnio: Azarien
OT
  • Rejestracja:około 20 lat
  • Ostatnio:ponad 11 lat
0

Biblioteka może być wielka, specjalistyczna, używać konstrukcji typowych dla C++

Może. Ale praktyka pokazuje, że często jest tak że potrzebujemy użyć tylko niewielkiej części dostępnych funkcjonalności, co łatwo ubrać w metody które da się potem wykorzystać w C#. Mowa oczywiście nie o setkach plików .cpp tylko np. zamkniętej bibliotece dll napisanej w c++, która eksportuje różne rzeczy.

Zreszta, zaciskanie zębów nic nie pomoże jeśli np. chcemy wpf zamiast przestarzałego winformsa.

edytowany 1x, ostatnio: othello
Azarien
na czym polega problem z WPF? „niedasie” z powodu jakich magicznych mechanizmów, czy po prostu brak odpowiedniego designera w Visualu?
OT
No jeśli chcesz rzeźbić ręcznie to może i się da, ale czy to ma jakiś sens w ogóle? Bo nie wydaje mi się.
Azarien
sensu pewnie nie, bo przecież jest WinForms. ale „rzeźbiłem” już w ten sposób LINQ, WCF i Solver Foundation. wszystko działa, mimo że miejscami wygląda jak pokazany kod Reva, albo jeszcze gorzej.
somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:około 9 godzin
  • Lokalizacja:Wrocław
2
Azarien napisał(a)

C++/CLI jest dla mnie najbardziej naturalnym wyborem jeśli mam na szybko napisać aplikację GUI, pod Windows, w C++.

Ale po co pisać aplikację GUI pod Windows w udziwnionym C++? Jakiś praktyczny przykład?

Azarien
Jest biblioteka w C++, jedyna w swoim rodzaju. Trzeba zrobić proste GUI. Nie chce mi się pisać wrappera, do którego i tak trzeba będzie napisać GUI.
OT
  • Rejestracja:około 20 lat
  • Ostatnio:ponad 11 lat
0

Pytacie czemu ludzie zaczynają od C++/CLI zamiast C#? Ano przez takie wpisy np: http://www.dobreprogramy.pl/Protected_48/CCLI-Replikacja-prostego-kalkulatora,31485.html - pytanie PO CO było to robić w C++ zamiast w C#?

edytowany 1x, ostatnio: othello
Azarien
Ktoś może znać C++. Nie znać C#. Chce napisać aplikacyjkę, wybiera Visual Studio, zapewne Express. Wydaje mu się, że skoro zna C++ to od razu sobie poradzi, a nie musi się uczyć całego nowego języka C#. Jest to złudne, bo żeby pisać w C++/CLI i tak trzeba znać C#.
OT
Jeśli ktoś zna C++ to przejście na C# nie jest trudne. Wręcz przeciwnie - na każdym kroku przekonujesz się to, czego brakowało ci w C++, jest w C#.
vpiotr
Albo ktoś może nie czuć potrzeby przechodzenia na C#, bo jest Java, Objective-C, Scala. Albo ktoś po prostu lubi robić przenośny kod. Albo ma fanaberię pisania w C++ na iSeries / OS/390...
NE
  • Rejestracja:ponad 11 lat
  • Ostatnio:ponad 11 lat
  • Postów:6
1

No,właśnie C# jest następcą C++,bo C# zostało stworzone w 2000 a C++ w 1979
Dane wzięte żywcem z wikipedii :)

somekind
Nie, nie jest.
aurel
A ja jestem następcą Napoleona...
CS
Nie jest. Czytałeś może o tym że ma wyjść C++14?
spartanPAGE
@CSharp gwoli ścisłości, C++14 wyszło już jakiś czas temu, teraz szykuje się C++17
Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 14 godzin
0

Zastanawiające, że ostatnio mamy wysyp pytań na forum dotyczących Windows Forms w C++/CLI.

I to w VS2013, gdzie nie da się przypadkiem kliknąć takiego typu projektu, bo go nie ma - trzeba wiedzieć że coś takiego istnieje i albo otworzyć projekt utworzony pod VS2010, albo stworzyć projekt konsolowy i pozmieniać w opcjach.

Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)