Информация об изменениях

Сообщение Re[4]: Microsoft исключит C++ к 2030 году... от 24.12.2025 17:55

Изменено 24.12.2025 17:57 Shmj

Re[4]: Microsoft исключит C++ к 2030 году...
Здравствуйте, sergii.p, Вы писали:

SP>не понимаю какого ООП вам там не хватает? Трейты — фактически абстрактные классы. Указатели есть. Пример на С++ который трудно/невозможно написать на Rust в студию.


Ну вот пример:

С++

  Скрытый текст
#include <iostream>
#include <memory>

class Base1 {
public:
    virtual ~Base1() = default;

    virtual  void fun1() const {
        std::cout << "fun1=" << a << std::endl;
    }

    virtual void fun2() const {
        std::cout << "fun2=" << a << std::endl;
    }

    virtual void fun3() const {
        std::cout << "fun3=" << a << std::endl;
    }

    virtual void fun4() const {
        std::cout << "fun4=" << a << std::endl;
    }
private:
    int a = 0;
};

class V1 : public Base1 {
public:
    void fun1() const override {
        std::cout << "_fun1=" << a << std::endl;
    }
private:
    int a = 1;
};

class V2 : public V1 {
public:
    void fun2() const override {
        std::cout << "__fun2=" << a << std::endl;
    }
private:
    int a = 2;
};

class V3 final : public V2 {
public:
    void fun3() const override {
        std::cout << "___fun2=" << a << std::endl;
    }
private:
    int a = 3;
};

int main() {
    const auto v3 = std::make_unique<V3>();

    v3->fun1();
    v3->fun2();
    v3->fun3();
    v3->fun4();

    return 0;
}


Т.е. в наследнике вы трогаете только то что отличается. Все просто 3 класса, поочередно наследуются. Это может быть как UI-виджеты так и некая система событий.

А вот Rust аналог авто-генеренный

Куча сущностей вместо трех простых записанных, намноОООго сложнее для восприятия. Т.е. теряется простота. А в последнем V3 вам еще нужно помнить что было переписано в V3 — это на малом количестве методов — а если их будут сотни?

В общем — слишком сложный для восприятия ООП-код получается. Не пригодно для промышленного использования.

  Скрытый текст
trait Base1Ops {
    // доступ к "Base1::a"
    fn base1_a(&self) -> i32;

    // виртуальные методы (есть дефолт, как в Base1)
    fn fun1(&self) {
        println!("fun1={}", self.base1_a());
    }
    fn fun2(&self) {
        println!("fun2={}", self.base1_a());
    }
    fn fun3(&self) {
        println!("fun3={}", self.base1_a());
    }
    fn fun4(&self) {
        println!("fun4={}", self.base1_a());
    }
}

struct Base1 {
    a: i32,
}

impl Base1 {
    fn new() -> Self {
        Self { a: 0 }
    }
}

impl Base1Ops for Base1 {
    fn base1_a(&self) -> i32 {
        self.a
    }
}

struct V1 {
    base: Base1,
    a: i32, // V1::a
}

impl V1 {
    fn new() -> Self {
        Self {
            base: Base1::new(),
            a: 1,
        }
    }
}

impl Base1Ops for V1 {
    fn base1_a(&self) -> i32 {
        self.base.a
    }

    fn fun1(&self) {
        println!("_fun1={}", self.a);
    }
}

struct V2 {
    v1: V1,
    a: i32, // V2::a
}

impl V2 {
    fn new() -> Self {
        Self { v1: V1::new(), a: 2 }
    }
}

impl Base1Ops for V2 {
    fn base1_a(&self) -> i32 {
        self.v1.base.a
    }

    // наследуем поведение V1::fun1
    fn fun1(&self) {
        self.v1.fun1();
    }

    fn fun2(&self) {
        println!("__fun2={}", self.a);
    }
}

struct V3 {
    v2: V2,
    a: i32, // V3::a
}

impl V3 {
    fn new() -> Self {
        Self { v2: V2::new(), a: 3 }
    }
}

impl Base1Ops for V3 {
    fn base1_a(&self) -> i32 {
        self.v2.v1.base.a
    }

    // наследуем поведение V1::fun1 и V2::fun2
    fn fun1(&self) {
        self.v2.fun1();
    }
    fn fun2(&self) {
        self.v2.fun2();
    }

    fn fun3(&self) {
        // в исходнике строка "___fun2=" (хотя это fun3) — сохраняю как есть
        println!("___fun2={}", self.a);
    }
    // fun4 не переопределяем => будет Base1-версия через дефолт
}

fn main() {
    let v3 = Box::new(V3::new());

    v3.fun1();
    v3.fun2();
    v3.fun3();
    v3.fun4();
}
Re[4]: Microsoft исключит C++ к 2030 году...
Здравствуйте, sergii.p, Вы писали:

SP>не понимаю какого ООП вам там не хватает? Трейты — фактически абстрактные классы. Указатели есть. Пример на С++ который трудно/невозможно написать на Rust в студию.


Ну вот пример:

С++

  Скрытый текст
#include <iostream>
#include <memory>

class Base1 {
public:
    virtual ~Base1() = default;

    virtual  void fun1() const {
        std::cout << "fun1=" << a << std::endl;
    }

    virtual void fun2() const {
        std::cout << "fun2=" << a << std::endl;
    }

    virtual void fun3() const {
        std::cout << "fun3=" << a << std::endl;
    }

    virtual void fun4() const {
        std::cout << "fun4=" << a << std::endl;
    }
private:
    int a = 0;
};

class V1 : public Base1 {
public:
    void fun1() const override {
        std::cout << "_fun1=" << a << std::endl;
    }
private:
    int a = 1;
};

class V2 : public V1 {
public:
    void fun2() const override {
        std::cout << "__fun2=" << a << std::endl;
    }
private:
    int a = 2;
};

class V3 final : public V2 {
public:
    void fun3() const override {
        std::cout << "___fun2=" << a << std::endl;
    }
private:
    int a = 3;
};

int main() {
    const auto v3 = std::make_unique<V3>();

    v3->fun1();
    v3->fun2();
    v3->fun3();
    v3->fun4();

    return 0;
}


Т.е. в наследнике вы трогаете только то что отличается. Все просто 3 класса, поочередно наследуются. Это может быть как UI-виджеты так и некая система событий.

А вот Rust аналог авто-генеренный

Куча сущностей вместо трех простых записанных, намноОООго сложнее для восприятия. Т.е. теряется простота. А в последнем V3 вам еще нужно помнить что было переписано в V2 — это на малом количестве методов — а если их будут сотни?

В общем — слишком сложный для восприятия ООП-код получается. Не пригодно для промышленного использования.

  Скрытый текст
trait Base1Ops {
    // доступ к "Base1::a"
    fn base1_a(&self) -> i32;

    // виртуальные методы (есть дефолт, как в Base1)
    fn fun1(&self) {
        println!("fun1={}", self.base1_a());
    }
    fn fun2(&self) {
        println!("fun2={}", self.base1_a());
    }
    fn fun3(&self) {
        println!("fun3={}", self.base1_a());
    }
    fn fun4(&self) {
        println!("fun4={}", self.base1_a());
    }
}

struct Base1 {
    a: i32,
}

impl Base1 {
    fn new() -> Self {
        Self { a: 0 }
    }
}

impl Base1Ops for Base1 {
    fn base1_a(&self) -> i32 {
        self.a
    }
}

struct V1 {
    base: Base1,
    a: i32, // V1::a
}

impl V1 {
    fn new() -> Self {
        Self {
            base: Base1::new(),
            a: 1,
        }
    }
}

impl Base1Ops for V1 {
    fn base1_a(&self) -> i32 {
        self.base.a
    }

    fn fun1(&self) {
        println!("_fun1={}", self.a);
    }
}

struct V2 {
    v1: V1,
    a: i32, // V2::a
}

impl V2 {
    fn new() -> Self {
        Self { v1: V1::new(), a: 2 }
    }
}

impl Base1Ops for V2 {
    fn base1_a(&self) -> i32 {
        self.v1.base.a
    }

    // наследуем поведение V1::fun1
    fn fun1(&self) {
        self.v1.fun1();
    }

    fn fun2(&self) {
        println!("__fun2={}", self.a);
    }
}

struct V3 {
    v2: V2,
    a: i32, // V3::a
}

impl V3 {
    fn new() -> Self {
        Self { v2: V2::new(), a: 3 }
    }
}

impl Base1Ops for V3 {
    fn base1_a(&self) -> i32 {
        self.v2.v1.base.a
    }

    // наследуем поведение V1::fun1 и V2::fun2
    fn fun1(&self) {
        self.v2.fun1();
    }
    fn fun2(&self) {
        self.v2.fun2();
    }

    fn fun3(&self) {
        // в исходнике строка "___fun2=" (хотя это fun3) — сохраняю как есть
        println!("___fun2={}", self.a);
    }
    // fun4 не переопределяем => будет Base1-версия через дефолт
}

fn main() {
    let v3 = Box::new(V3::new());

    v3.fun1();
    v3.fun2();
    v3.fun3();
    v3.fun4();
}