您的位置:首页 > 房产 > 家装 > 网络营销的广告形式有哪些_个人网站系统_竞价系统_公司网站建设费

网络营销的广告形式有哪些_个人网站系统_竞价系统_公司网站建设费

2025/4/26 2:59:29 来源:https://blog.csdn.net/2301_79109608/article/details/146998173  浏览:    关键词:网络营销的广告形式有哪些_个人网站系统_竞价系统_公司网站建设费
网络营销的广告形式有哪些_个人网站系统_竞价系统_公司网站建设费

const关键字 

一、const关键字 
  1. 修饰成员变量

    • 常成员变量必须通过构造函数的初始化列表进行初始化,且初始化后不可修改。

    • 示例

      class Student { private: const int age; // 常成员变量 
      public: Student(string name, int age) : age(age) { ... }};
  2. 修饰成员函数

    • 常成员函数

      • 不能修改类的成员变量(编译时检查)。

      • 可以与普通成员函数构成重载,常对象只能调用常成员函数。

    • 示例

      class Student {
      public:const void show() { ... }          // 版本1:返回值为const voidconst void show() const { ... }    // 版本2:返回值为const void,且是const成员函数void show() const { ... }          // 版本3:返回值为void,且是const成员函数void show() { ... }                // 版本4:普通成员函数private:std::string name;int age;
      };const Student stu("Alice", 20);
      stu.show();  // 调用常成员函数版本
  3. 修饰对象

    • 常对象

      • 对象初始化后不可修改成员变量。

      • 只能调用常成员函数。

    • 示例

      const Student stu("Bob", 18);
      // stu.setAge(19);  // 错误:常对象不可修改成员变量
      stu.show();         // 正确:调用常成员函数
二、staticconst修饰构造函数和析构函数
  1. 构造函数

    • static修饰

      • 构造函数用于初始化对象实例,而static成员属于类层级,与对象实例化机制冲突。

      • 禁止:C++语法规定构造函数不能是static

    • const修饰

      • 构造函数需要修改对象状态(初始化成员变量),与const的不可修改语义矛盾。

      • 禁止:构造函数不能声明为const

  2. 析构函数

    • static修饰

      • 析构函数与对象生命周期绑定,而static成员属于类层级,无法处理具体实例的资源释放。

      • 禁止:析构函数不能是static

    • const修饰

      • 析构函数需要释放资源(如动态内存),而const限制成员变量的修改。

      • 禁止:析构函数不能声明为const

三、staticconst修饰成员变量和函数
  1. 成员变量

    • static const成员变量

      • 允许同时使用,表示类层级的常量(所有对象共享同一值)。

      • 必须在类外初始化(C++11后支持类内初始化)。

      • 示例

        class Math {
        public:static const double PI = 3.14159;  // 类内初始化(C++11)
        };
  2. 成员函数

    • staticconst同时修饰

      • 无意义static成员函数不关联对象实例(无this指针),而const要求不修改对象状态。

      • 禁止:C++语法不允许static成员函数声明为const

四、关键对比与注意事项
场景const修饰static修饰
成员变量必须初始化,不可修改类层级变量,所有对象共享
成员函数不能修改成员变量,支持重载this指针,不能访问非静态成员
对象只能调用常成员函数不适用(static不修饰对象)
构造函数/析构函数禁止(需修改对象状态)禁止(与对象生命周期绑定)

友元(Friend)

一、 友元(Friend)

1. 核心概念

  • 友元函数:允许外部普通函数访问类的私有成员,需在类内用 friend 声明。

  • 友元成员函数:允许另一个类的某个成员函数访问当前类的私有成员,需在类内声明该成员函数为友元。

  • 友元类:允许另一个类的所有成员函数访问当前类的私有成员,需在类内声明友元类。

2. 特点

  • 单向性:友元关系不可逆(若类A是类B的友元,类B不自动成为类A的友元)。

  • 无继承性:基类的友元不是派生类的友元。

  • 无传递性:若类A是类B的友元,类B是类C的友元,类A不自动成为类C的友元。

3. 应用场景

  • 运算符重载(如 operator<< 用于输出)。

  • 跨类协作(如矩阵类与向量类共享数据)。

  • 工具函数需要访问私有成员时(如调试函数)。

4. 示例代码

#include <iostream>
#include <string>
using namespace std;// 友元函数
class Student {
private:string name;int age;
public:Student(const string &n, int a) : name(n), age(a) {}friend void printStudent(const Student& s); // 声明友元函数
};void printStudent(const Student& s) {cout << "Name: " << s.name << ", Age: " << s.age << endl; // 直接访问私有成员
}// 友元类
class Display {
public:void show(const Student& s);
};class Student {
private:string name;int age;
public:Student(const string &n, int a) : name(n), age(a) {}friend class Display; // 声明友元类
};void Display::show(const Student& s) {cout << "Name: " << s.name << ", Age: " << s.age << endl; // 直接访问私有成员
}// 补充一个友元成员函数
class Student {
private:string name;int age;
public:Student(const string &n, int a) : name(n), age(a) {}friend class Display; // 声明友元类friend void compareStudents(const Student& s1, const Student& s2); // 声明友元成员函数
};// 定义友元成员函数,比较两个Student对象的年龄
void compareStudents(const Student& s1, const Student& s2) {if (s1.age > s2.age) {cout << s1.name << " is older than " << s2.name << endl;} else if (s1.age < s2.age) {cout << s2.name << " is older than " << s1.name << endl;} else {cout << s1.name << " and " << s2.name << " are the same age" << endl;}
}int main() {Student s1("Alice", 20);Student s2("Bob", 22);// 使用友元函数printStudent(s1); // 输出: Name: Alice, Age: 20// 使用友元类Display d;d.show(s2); // 输出: Name: Bob, Age: 22// 使用友元成员函数compareStudents(s1, s2); // 输出: Bob is older than Alicereturn 0;
}

运算符重载(Operator Overloading)

一、运算符重载(Operator Overloading)

1. 核心概念

  • 定义:赋予运算符对自定义类类型对象的功能。

  • 格式返回类型 operator运算符(参数列表)

  • 形式

    • 非成员函数:通常声明为友元以访问私有成员。

    • 成员函数:隐含 this 指针,左操作数为当前对象。

2. 常见运算符重载规则

  • 加法运算符(+)成员函数

    String String::operator+(const String &op2){int len = strlen(this->str)+strlen(op2.str)+1;String newStr;newStr.str = new char[len];strcpy(newStr.str,this->str);strcat(newStr.str,op2.str);return newStr;
    }
  • 自增运算符(++)

    • 前置++String& operator++();

    • 后置++String operator++(int);(通过哑元参数区分)

  • 下标运算符([])

    char &String::operator[](int index)const{//检查索引是否越界,必须满足在固定的长度内if (index < 0 || index >= this->size) {static char nullChar = '\0'; // 定义一个静态字符return nullChar; // 返回静态字符的引用}return this->str[index];
    }

3. 关键注意事项

  • 内存管理:运算符重载中若涉及动态内存(如字符串拼接),需实现深拷贝。

  • 返回值优化:返回临时对象时,优先通过构造函数优化(如 return String(buffer);)。

  • 异常处理:下标访问需检查索引范围,防止越界。

4. 示例代码

// 加法运算符重载(非成员函数)
String operator+(const String& a, const String& b) {char* buffer = new char[a.length + b.length + 1];strcpy(buffer, a.str);strcat(buffer, b.str);String result(buffer);delete[] buffer;return result;
}// 自增运算符重载(成员函数)
String& String::operator++() { // 前置++for (char* p = str; *p; p++) (*p)++;return *this;
}String String::operator++(int) { // 后置++String temp(*this); // 调用拷贝构造函数++(*this);          // 调用前置++return temp;
}

2. 实现String类的下标运算符重载

char &String::operator[](int index)const{//检查索引是否越界,必须满足在固定的长度内if (index < 0 || index >= this->size) {static char nullChar = '\0'; // 定义一个静态字符return nullChar; // 返回静态字符的引用}return this->str[index];
}
二、赋值运算符(=)重载
  1. 核心作用
    实现对象间的深拷贝,避免浅拷贝导致的内存重复释放或泄漏。

  2. 实现要点

    • 自赋值检查:防止 a = a 导致内存错误。

    • 释放旧内存:赋值前需释放当前对象的资源。

    • 深拷贝新内存:重新分配内存并复制内容。

  3. 代码示例

    String &String::operator=(const String &obj)
    {if (this != &obj){ // Exclude the scenario where this points to objif (this->str != NULL){delete[] this->str;}if (obj.str != NULL){int len = strlen(obj.str) + 1;this->str = new char[len];strcpy(this->str, obj.str);}}return *this;
    }
  4. 注意事项

    • 必须为成员函数:C++规定赋值运算符只能通过成员函数重载。

    • 默认赋值运算符的陷阱:默认实现为浅拷贝,需手动重载以支持深拷贝。

三、左移运算符(<<)重载
  1. 核心作用
    支持自定义类的输出流操作(如 cout << obj)。

  2. 实现要点

    • 声明为友元函数:以访问类的私有成员。

    • 返回 ostream&:支持链式调用(如 cout << a << b)。

  3. 代码示例

    两种实现方法
    1、
    ostream &operator<<(ostream &os, const String &obj)
    {if (obj.str){os << obj.str;}return os;
    }
    2、
    class String {
    private:char* str;
    public:friend ostream& operator<<(ostream& os, const String& obj);
    };ostream& operator<<(ostream& os, const String& obj) {if (obj.str != nullptr) {os << obj.str;}return os;  // 返回流引用以支持链式调用
    }
  4. 注意事项

    • 输入运算符(>>)同理:需处理输入流并修改对象状态,通常声明为友元。

四、不能被重载的运算符
运算符不可重载原因
.成员访问运算符,重载会破坏语言基础结构。
::域运算符,属于编译时解析的语法结构。
sizeof计算对象大小,编译时确定,无法动态重载。
?:三目运算符,逻辑复杂且可能引发歧义。
.* 和 ->*成员指针访问运算符,语法特殊且用途有限。
五、运算符重载的通用规则
  1. 语法限制

    • 只能重载C++已有的运算符,不可创建新运算符(如 **)。

    • 不能改变运算符的优先级、结合性或操作数个数(如 + 始终为双目运算符)。

  2. 函数形式

    • 成员函数:适用于左操作数为当前类对象(如 a + b)。

    • 友元函数:适用于左操作数为其他类型(如 cout << obj)。

  3. 特殊运算符重载

    • 自增/自减运算符

      String& operator++();    // 前置++
      String operator++(int);  // 后置++(通过哑元参数区分)
    • 下标运算符([]):需提供 const 和非 const 版本。

      char &String::operator[](int index)const{//检查索引是否越界,必须满足在固定的长度内if (index < 0 || index >= this->size) {static char nullChar = '\0'; // 定义一个静态字符return nullChar; // 返回静态字符的引用}return this->str[index];
      }
       
六、常见问题与解决方案
问题原因解决方法
内存泄漏未释放旧内存在赋值运算符中先 delete[] 再 new
双重释放(double free)浅拷贝导致共享内存实现深拷贝
链式调用失败未返回流或对象引用返回 ostream& 或 String&

 继承

一、继承的核心概念
  1. 作用

    • 减少代码冗余:将多个类的公共属性和方法抽象到父类中,子类通过继承复用代码。

    • 增强扩展性:子类可添加特有属性或覆盖父类方法,实现功能扩展。

  2. 基本语法

    class 子类名 : 访问修饰符 父类名 {// 子类特有属性和方法
    };
    • 访问修饰符publicprotectedprivate,决定父类成员在子类中的可见性。

二、用户代码分析
  1. 原始问题

    • 多个英雄类(如 HanzinHouyi)中存在重复的“英雄的属性”,导致代码冗余。

  2. 优化思路

    • 将公共属性提取到基类 Hero 中,特定类型(如射手、法师)进一步抽象为中间类(如 Ranger),最终由具体英雄类继承。

三、继承体系设计示例
  1. 基类:Hero

    #ifndef __HERO_HEAD__
    #define __HERO_HEAD__
    #include <iostream>
    #include <string>
    using namespace std;
    class Hero
    {
    public:// 重构函数Hero(const string &name = "hero") : name(name) {};// 析构函数~Hero(){cout << "Hero 析构" << endl;}
    //英雄特有的名字给一个函数用于访问namestring get_name() const { return name; }void set_name(const string &name) { this->name = name; }virtual void show() const{cout << "Name: " << name << endl;}
    protected:string name;
    };#endif
  2. 中间类:Ranger(射手)

    #ifndef __RANGER_HEAD__
    #define __RANGER_HEAD__
    #include "hero.h"
    #include <iostream>
    using namespace std;
    class Ranger{   
    public:
    //构造函数Ranger(int distance):distance(distance){cout << "Ranger 构造函数" <<  endl;}
    //获取对应的射程int get_distance() const { return distance; }void set_distance(int distance) { this->distance = distance; }void show(){cout << "Distance: " << distance <<  endl;}~Ranger() {cout << "Ranger 析构函数" <<  endl;}private:int distance;
    };#endif
  3. 具体类:Drj(狄仁杰) 

    #ifndef DRJ_H
    #define DRJ_H
    #include "hero.h"
    #include "ss.h"
    #include <string>
    #include <iostream>class Drj : public Ranger,public Hero{  // 仅继承 Ranger(已虚继承 Hero)
    private:std::string looks;public:Drj(const std::string &name, int distance, const std::string &looks):Hero(name),Ranger(distance),looks(looks){std::cout << "Drj 构造函数" << std::endl;}void show()const{Hero::show();  // 调用 Hero 的 show()std::cout << "Looks: " << looks << std::endl;}~Drj(){std::cout << "Drj 析构函数" << std::endl;}
    };#endif

    4.Hero_main.cpp:

#include <iostream>
#include "hero.h"
#include "ss.h"
#include "drj.h"int main() {/*若是直接用private:或protected:继承都会出现继承范围越来越小,以至于在主函数中都无法使用因此利用public直接继承值或是public函数辅助访问私有或是保护的值*/// 创建 Hero 对象Hero hero("基础英雄");hero.show();std::cout << "-----------------" << std::endl;// 创建 Ranger 对象攻击范围是100Ranger ranger(100);ranger.show();std::cout << "-----------------" << std::endl;// 创建 Drj 对象Drj drj("狄仁杰", 150, "英俊");drj.show();std::cout << "-----------------" << std::endl;return 0;
}

 结果显示:

六、继承的优势与注意事项

  1. 优势

    • 代码复用:公共逻辑集中管理,减少重复代码。

    • 层次化设计:通过多级继承实现模块化开发(如 Hero → Ranger → Houyi)。

  2. 注意事项

    • 访问权限:合理使用 publicprotectedprivate 控制成员可见性。

    • 菱形继承问题:避免多继承导致的二义性(可通过虚继承解决)。

    • 父类析构函数:若父类有虚函数,应声明虚析构函数以防止资源泄漏。

关键实践建议

  • 优先使用组合而非继承,避免过度设计。

  • 使用 protected 替代 private 以支持子类扩展。

  • 在复杂继承体系中,合理使用虚函数和多态特性。

四、菱形继承
1. 菱形继承的定义与结构

菱形继承(Diamond Inheritance) 是指一个派生类(如 D)通过多个路径继承自同一个基类(如 A)。具体结构如下:

  • 示例代码结构

    class A { public: int a; };  
    class B : public A {};  
    class C : public A {};  
    class D : public B, public C {}; 
    2. 菱形继承导致的问题
  • 成员重复
    由于 B 和 C 都继承自 AD 会包含两份 A 的成员变量 a(分别通过 B 和 C 继承)。

  • 访问歧义
    当在 D 中直接访问 a 时,编译器无法确定应使用 B::a 还是 C::a,导致编译错误。

示例错误代码

class D : public B, public C {  
public:  void function() {  a = 200;  // ❌ 错误:reference to 'a' is ambiguous  }  
};  int main() {  D object;  object.a = 100;  // ❌ 错误:request for member 'a' is ambiguous  return 0;  
}  
3. 编译器报错原因
  • 歧义性访问
    D 中存在两个独立的 A 子对象(分别来自 B 和 C),因此 a 在 D 中有两个副本。

  • 错误示例

    Test.cpp:18:17: error: reference to 'a' is ambiguous  
    Test.cpp:25:16: error: request for member 'a' is ambiguous 
4. 解决方法

通过 作用域解析运算符(:: 明确指定访问路径,消除歧义。

修改后代码

class D : public B, public C {  
public:  void function() {  B::a = 200;  // ✅ 明确指定访问 B 继承的 a  }  
};  int main() {  D object;  object.C::a = 100;  // ✅ 明确指定访问 C 继承的 a  return 0;  
}  
5. 其他解决方法(补充)
  • 虚继承(Virtual Inheritance)
    使用 virtual 关键字继承,确保 D 中只保留一份 A 的成员。

    class B : virtual public A {};  
    class C : virtual public A {};  
    class D : public B, public C {};
    • 优势:无需通过作用域解析符访问,直接使用 a

    • 注意:虚继承会增加对象内存布局的复杂性。

6. 关键结论
问题原因解决方案
成员重复与访问歧义多路径继承同一基类使用 B::a 或 C::a 明确路径
代码冗余多个基类副本虚继承(推荐)
五、访问修饰符 
1、类成员的访问修饰符
修饰符类内部访问子类访问类外访问
public
protected
private

核心规则

  • public:完全开放访问。

  • protected:仅限类内部和子类访问。

  • private:仅限类内部访问。

2、继承方式对成员权限的影响
继承方式基类 public 成员基类 protected 成员基类 private 成员
public保持 public保持 protected不可访问
protected降级为 protected保持 protected不可访问
private降级为 private降级为 private不可访问

核心规则

  • 继承方式决定了基类成员在派生类中的访问权限上限。

  • private 成员始终不可被派生类直接访问。

3、示例代码分析
基类定义
  1. B1 类

    class B1 {
    public:int i;      // public
    protected:int k;      // protected
    };
  2. B2 类(修正变量名 1 为 l):

    class B2 {
    public:int l;      // public
    private:int m;      // private
    protected:int q;      // protected
    };
  3. B3 类

    class B3 {
    public:int p1;     // public
    };
派生类 C 的继承方式
class C : public B2, protected B1, private B3 {
public:int c;      // 新增 public 成员
};
成员权限推导
基类成员原始权限继承方式在 C 中的权限是否可外部访问
B2::lpublicpublic 继承public
B2::qprotectedpublic 继承protected
B1::ipublicprotected 继承protected
B1::kprotectedprotected 继承protected
B3::p1publicprivate 继承private
C::c--public

组合

一、组合的核心概念
  • 定义:组合是通过将现有类的对象作为成员嵌入到新类中,构建“整体-部分”关系(即“has-a”或“contains-a”关系)。

  • 典型场景

    • 汽车(Car)包含引擎(Engine)和轮胎(Wheel)。

    • 英雄(Houyi)拥有皮肤(Skin)。

二、组合的实现方式
1. 基本语法
class NewClass {
public:// 成员函数
private:Class1 obj1;  // 组合:包含 Class1 对象Class2 obj2;  // 组合:包含 Class2 对象
};
2. 示例代码分析
class Houyi : public Hero, public Ranger {
public:Houyi(const string &name, int distance, int looks, int price, const string &appearance);~Houyi();void show() const;private:int looks;Skin skin;  // 组合:Skin 对象作为成员
};// 构造函数初始化列表必须显式初始化成员对象
Houyi::Houyi(...) : Hero(name), Ranger(distance), skin(price, appearance) {// 派生类自身逻辑
}
3. 关键规则
  • 成员对象初始化:必须在构造函数的初始化列表中显式调用成员对象的构造函数。

  • 默认构造函数:若未显式初始化,成员对象会调用其默认构造函数(若存在)。

三、构造函数与析构函数的调用顺序
  1. 构造函数调用顺序

    • 按继承顺序调用基类构造函数(Hero → Ranger)。

    • 按成员对象声明顺序调用成员对象的构造函数(Skin)。

    • 最后调用派生类自身的构造函数(Houyi)。

  2. 析构函数调用顺序:与构造函数顺序相反。

    • 先调用派生类的析构函数。

    • 再按成员对象声明逆序调用析构函数(Skin)。

    • 最后按继承逆序调用基类析构函数(Ranger → Hero)。

四、继承与组合的对比
特性继承(is-a)组合(has-a)
关系类型子类是父类的一种特化整体包含部分
耦合度高耦合(父类改动影响子类)低耦合(通过接口交互)
代码复用直接复用父类方法通过成员对象复用功能
灵活性低(编译时绑定)高(运行时动态替换成员对象)
设计原则易违反封装原则符合信息隐藏原则
五、组合的优缺点
优点
  1. 低耦合:成员对象通过接口交互,隐藏实现细节。

  2. 动态扩展:可在运行时替换成员对象(例如更换引擎)。

  3. 强封装性:成员对象的内部细节对整体类不可见。

缺点
  1. 对象数量增多:可能导致内存占用增加。

  2. 接口设计复杂:需设计清晰的接口协调多个成员对象。

六、组合的应用示例

任务:为“狄仁杰”类添加 Skin 成员并显示信息

class DiRenJie : public Hero {
public:DiRenJie(const string &name, int skillLevel, const Skin &skin) : Hero(name), skin(skin), skillLevel(skillLevel) {}void showInfo() const {cout << "Name: " << getName() << endl;cout << "Skill Level: " << skillLevel << endl;cout << "Skin: " << skin.getAppearance() << " (Price: " << skin.getPrice() << ")" << endl;}private:int skillLevel;Skin skin;  // 组合:包含 Skin 对象
};

  • 这是本人的学习笔记不是获利的工具,小作者会一直写下去,希望大家能多多监督
  • 文章会每攒够两篇进行更新发布(受平台原因,也是希望能让更多的人看见)
  • 感谢各位的阅读希望我的文章会对诸君有所帮助

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com